最近尝试着写dom库,发现了一个问题,就是jquery不用new就可以得到相应的对象实例,好奇之下发现网上已经有很多的分析和解释啦,但是看起来还是那么绕绕绕~~ 没关系,来慢慢理解看看呗。先看最关键的几个源代码 jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); } jQuery.fn = jQuery.prototype = { jquery: version, constructor: jQuery, ... } init = jQuery.fn.init = function( selector, context, root ){} init.prototype = jQuery.fn; window.jQuery = window.$ = jQuery; 具体实现就不贴了,很复杂怕怕。。。就单说无new化,其实就是$()就是调用了jQuery这个构造函数,而这个函数里面是返回的一个new的init构造方法,所以实际上$()拿到的jquery对象的构造函数是init。这里很容易有两个问题让人迷惑。
jQuery = function( selector, context ) { return new jQuery( selector, context ); } 矣。。很多分析的文章也都会提到,死循环了。。。所以可以想出,方法想要返回一个new好的实例,new该方法本身肯定是不行的,因为一个方法既想返回一个对象,又想把自己的实例返回去,这两个职责是矛盾的,所以怎么办呢,借助另一个构造函数呗?ok,那么问题2来了,也很困扰我。。。
是啊,我直接用一个新的函数作为构造函数不行么,比如: var init = function( selector, context ) {} 又或者挂到jQuery上?比如: jQuery.init = function( selector, context ) {} 为什么偏偏挂到了jQuery.fn.init上呢?????真是让人头大啊,为啥呢????绕来绕去是为啥呢?而且注意到这句 init = jQuery.fn.init = function( selector, context, root ){} init.prototype = jQuery.fn; 为了让jQuery.fn.init构造函数new出的对象能够使用jQuery原型上的方法还要重新赋值一下,那其实这些用另外两种方式都可以啊,为啥还是挂在了jQuery.fn.init上呢? 在网上搜索了不少答案都不是很清晰,欢迎大神们指教。有一种说法感觉有些道理,就是说如果在jquery代码外部,用户希望用jquery实例调用init方法来实例化一个jquery对象(什么场景会用到呢?实例化直接$()不就得了,用什么init啊,有一种场景就是比如你想继承jquery类,这个时候在子构造方法里使用init()来使用父的构造方法,也就是这种写法有利于继承,而以上两种我说的写法的第一种var init没有暴露不能这么调用,而第二种jQuery.init挂在了类上,实例并不能调用。)以下是stack上一段代码的解释。 function MyJQuery(selector, context) { this.init(selector, context, MyJQuery.root); // <== // or more explicit: // jQuery.fn.init.call(this, selector, …); … } MyJQuery.fn = MyJQuery.prototype = Object.create(jQuery.fn); MyJQuery.root = jQuery(document); 嗯嗯,,绕把绕吧,绕绕更健康哈哈哈哈~ (责任编辑:好模板) |