最近有人问 jQuery 的构造函数为什么写的那么奇怪,不好理解。
其实我刚开始看 jQuery 源码的时候也有这个疑问,下面是 jQuery 构造函数的关键代码:
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context );
},
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
}
init = jQuery.fn.init = function( selector, context ) {
return jQuery.makeArray( selector, this );
}
虽然只有短短几行,但是不理解构造函数和原型链的童鞋很容易产生这么几个疑问:
return new jQuery.fn.init( selector, context );
而不是 return this
或者省略fn
和 prototype
是什么关系,为什么要叫 fn
constructor: jQuery
是干嘛的init
函数里面返回的是什么首先说说第一个问题,这个问题是关键。我们一般的构造函数都是这样的:
People = function() {
return this;//这一行可有可无
}
其中 return this
有没有都无所谓。因为在JS中,通过 new
关键字创建的对象,遵守如下规则:
return this
而我们再看 jQuery
的构造函数:
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context );
},
这里返回了一个对象,因此,我们用不用 new
关键字都是一样的,最终得到的都是一个 new jQuery.fn.init( selector, context );
实例。
对!这就是它的这一奇怪的构造函数写法的目的,就是为了能让我们在创建 jQuery
对象的时候省略 new
关键字:
a = $(“a”);
但是这样做有一个副作用,就是 a
其实不是 jQuery
的实例,而是 jQuery.fn.init
的实例。所以需要修正一下 constructor
:
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
}
这样我们用 a instanceof jQuery
的时候就不会返回 false
了:
a instanceof jQuery; //true
a instanceof jQuery.fn.init; //true
那么那个奇怪的 fn
是干嘛的?其实 fn
就是一个 prototype
的别名而已,因为 prototype
名字太长了写起来麻烦,并且由于是特殊属性在压缩代码的时候无法被压缩, 他们完全是等价的。
这样前三个问题我们都有答案了,至于最后一个问题 return jQuery.makeArray( selector, this );
返回的是啥玩意?看看 makeArray
的代码就知道了,其实返回的就是 this
。
所以总结一下,jQuery 的构造函数为什么写的这么奇怪?归根结底原因很简单,就是为了能在创建 jQuery
对象的时候省略一个 new
关键字。为了让大家用的爽,真是用心良苦啊。