/*
1、如何实现jQuery(selector).do().
var jQuery = function(selector, context) {
return new jQuery();
}
jQuery.prototype = {
name: function() {},
age: function() {}
}
这样的话,代码陷入死循环了!
*/
//每次执行函数都产生新的实例并直接应用,makeCar().getModel()
//不需要采用var car = new Car('Eagle', 'Talon TSi', 1993),car.name的方式
//函数运行后得到实例然后直接使用,这也是jquery的便利的起点。
function Car(make, model, year) {
this.make = make;
this.getModel = function() {return model};
this.year = year;
}
function makeCar(){
return new Car('makeCar().make', 'makeCar().getModel()', 1993);
}
console.log(makeCar().make);
console.log(makeCar().getModel());
const car1 = new Car('car1.make', 'car1.getModel()', 1993);
console.log(car1.make);
console.log(car1.getModel());
/*
2、不用new情况下如何?
this指向调用它的对象。
所以,下面this永远指向jQueryOne.prototype,
也就是每次返回对象都是jQueryOne.prototype,而不是实例对象。
*/
var jQueryOne = function(selector, context) {
return jQueryOne.prototype.init();//不用new情况下
}
jQueryOne.prototype = {
init: function() {
this.name=function() {return "jQueryOne init"};
//这里的 this 指向原型对象,所以会覆盖掉定义中的name: function() {return "jQueryOne"},
console.log("this===jQueryOne.prototype: "+(this===jQueryOne.prototype));
return this;
// 这里的 this 指向原型对象,所以执行jQueryOne.prototype.init()后,
//实际上返回的是jQueryOne.prototype,也就不能构造不同的实例。
},
name: function() {return "jQueryOne"},
age: function() {return 18}
}
console.log(jQueryOne().name());
console.log(jQueryOne().age());//init里面为定义age,但是this指向的是prototype,所以可以访问prototype的方法。
//> jQueryOne init
//> 18
console.log("==========="+(jQueryOne().name===jQueryOne.prototype.name))//true
console.log("==========="+(jQueryOne().name===jQueryOne().name))//false?????????为什么都是jQueryOne.prototype.name却不等?
/*
3、new情况下如何?
使用new,每次都生成新的实例,这里的 this 指向 new init 生成的对象,和prototype无关。
*/
var jQueryNew = function(selector, context) {
return new jQueryNew.prototype.init();//使用new。
}
jQueryNew.prototype = {
init: function() {
this.name = function() {return "jQueryNew initName"};
console.log("this===jQueryNew.prototype: "+(this===jQueryOne.prototype));
return this; // 使用new,这里的 this 指向 new init 生成的对象,和prototype无关。
},
name: function() {return "jQueryNew"},
age: function() {return 18}
}
console.log(jQueryNew().name());
//console.log(jQueryNew().age());
//> jQueryNew initName
//> Uncaught TypeError: jQueryNew(...).age is not a function
//jQueryNew().age()无法执行的原因:jQueryNew()是init的实例,实例代码中只有name方法,没有age方法。
//age方法属于jQueryNew.prototype ,和int实例无关。如何让init的实例可以访问jQueryNew.prototype的方法。
/*
4、实例访问原型方法:
使用new,每次都生成新的实例,这里的 this 指向 new init 生成的对象,和jQueryNewAndRnewPro.prototype无关。
将jQueryNewAndRnewPro.prototype赋值给init.prototype后,init的实例就可以通过原型访问到jQueryNewAndRnewPro.prototype方法。
*/
var jQueryNewAndRnewPro = function(selector, context) {
return new jQueryNewAndRnewPro.prototype.init();//使用new。
}
jQueryNewAndRnewPro.prototype = {
init: function() {
this.name = function() {return "jQueryNewAndRnewPro initName"};
return this; // 使用new,这里的 this 指向 new init 生成的对象,和prototype无关。
},
name: function() {return "jQueryNewAndRnewPro"},
age: function() {return 18}
}
jQueryNewAndRnewPro.prototype.init.prototype = jQueryNewAndRnewPro.prototype;
//将jQueryNewAndRnewPro.prototype.init.prototype 指向jQueryNewAndRnewPro.prototype后,就可以访问其原型方法
console.log(jQueryNewAndRnewPro().name());
console.log(jQueryNewAndRnewPro().age());
//> jQueryNewAndRnewPro initName
//> 18
//简化jquery代码
//init为什么放到原型上?不在原型上如何?
//任何jquery实例可以访问init,为什么?
(function () {
"use strict";
var version = "3.5.1",
jQuery = function jQuery(selector, context) {
return new jQuery.fn.init(selector, context);
};
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
jquery: version,
length: 0,
};
var init = jQuery.fn.init = function init(selector, context, root) {
//...
};
init.prototype = jQuery.fn;
//...
window.jQuery = window.$ = jQuery;
console.log(jQuery().init);
})();
//init不放到原型上
(function () {
"use strict";
var version = "3.5.1",
jQuery = function jQuery(selector, context) {
return new jQuery.init(selector, context);
};
jQuery.prototype = {
constructor: jQuery,
jquery: "1111",
length: 0,
};
jQuery.init = function init(selector, context, root) {
console.log("init begin");
};
jQuery.init.prototype = jQuery.prototype
//...
console.log(jQuery().jquery);
})();
//任意init
(function () {
"use strict";
var version = "3.5.1",
jQuery = function jQuery(selector, context) {
return new init(selector, context);
};
jQuery.prototype = {
constructor: '',
jquery: "1111",
length: 0,
};
var init = function init(selector, context, root) {
console.log("init begin");
};
init.prototype = jQuery.prototype
//...
console.log(jQuery().jquery);
})();
/*
执行 $([selector]) 方法,过程如下
相当于执行 new jQuery.fn.init(selector, context); ,返回的是 init 方法(类)的实例,假设这个实例是 A
那么: 可以得出 A.__proto__===init.prototype
又由代码可以得知 init.prototype => jQuery.fn => jQuery.prototype ,让 init 的原型重定向为jQuery的原型,所以最终执行 new init 相当于执行了 new jQuery
所以 A.__proto__===jQuery.prototype
总结:基于JQ选择器 $(...) 、 jQuery(...) 获取的是 jQuery 类的实例
目的:让用户使用的时候把 jQuery / $ 当做普通函数执行,但是最后的结果是创造其类的一个实例,用户使用起来方便
这种处理模式的思想其实就是工厂设计模式
*/
console