读了几次jquery创建对象的部分的源码都没读懂,今天终于想通了,持续兴奋中。。。
(一)、首先说明下jquery的对象创建方式:
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context );
};
jQuery.fn = jQuery.prototype = {
init:function(){ console.log('---in init---');
return this;
},
jquery: version,
constructor: jQuery,
………………
};jQuery.fn.init.prototype = jQuery.fn;
大致说明如下:
对外的接口jQuery()本质上通过工厂模式创建并返回了一个new出来的jquery对象;jquery的构造函数实现在jquery.fn的init方法中;
为什么这么绕???
(二)、自己写了一个小demo解释一切
var Fairy = function(opt) { return new Fairy.prototype.init(opt); }; Fairy.prototype = { name: 'Fairy', init: function(opt) { console.log(this.name); return this; } } // Fairy.prototype.init.prototype = Fairy.prototype;一、控制台调用的结果(注释掉最后一行):
1、执行Fairy():
输出:undefined
2、执行Fairy.prototype.init():
输出:Fairy
二、控制台调用的结果(取消注释最后一行Fairy.prototype.init.prototype = Fairy.prototype):
1、执行Fairy():
输出:Fairy
2、执行Fairy.prototype.init():
输出:Fairy
(三)、解释如下:
1、执行new Fairy.prototype.init()大致做了几件事:
申请一个新地址addr1;
将Fairy.prototype.init()方法中的指令拷贝到当前地址addr1,注意包括方法隐藏的__proto__关联的Fairy.prototype.init方法的原型方法的地址(最后一行注释掉的情况下,遍历原型链时应该关联到老祖宗Object上去了);
执行add1中的指令;
返回add1(新对象的访问地址);
2、最后一行注释掉的情况下,执行new Fairy.prototype.init()时,this指add1,这个地址对应的环境中并没有name属性,上游原型prototype(即Object)中也没有该属性,因此返回undefined;
3、最后一行注释掉的情况下,执行Fairy.prototype.init()时,this指Fairy.prototype对象的地址,这个地址对应的环境中有name属性,可以访问到;
4、取消最后一行注释掉的情况下,执行new Fairy.prototype.init()时,this指add1,这个地址对应的环境中并没有name属性,上游原型prototype为Fairy.prototype对象,该对象中有该属性,因此借助原型链机制访问到了;
5、取消最后一行注释掉的情况下,执行Fairy.prototype.init()时,this指Fairy.prototype对象的地址,这个地址对应的环境中有name属性,可以访问到;
(四)、总结
之所以这么绕,是为了方便jQuery.prototype中的属性或方法能够通过new(即实例方法)和静态工具方法都能调用到~
大脑都快想跪掉了,终于整通了!
跪服。。。