jquery内部实现原理分析
我们经常用jquery的选择器,甚至为jquery写插件写扩展,今天来讨论一下jquery内部的实现原理(基于jquery-1.11.1.js)。
一、关于window.$和window.jQuery
其实在jquery中最开始只定义了一个jQuery局部变量,就是一个函数对象,即如下的形式
jQuery=function(selector, context){
....
}
在jquery的末尾位置处,才将jQuery局部变量赋值给了window.$和window.jQuery,即window.$ = window.jQuery = jQuery;
这里需要说明的是,jQuery指向的匿名函数对象如果仅仅从形式上看,它甚至不一定返回一个对象,因为javascript是动态语言具有函数式编程的特性,可以返回函数(虽然在javascript中函数也是对象但是函数对象和实例对象是不一样的),或者以函数作为参数,当然也可以返回对象和基本类型。
jQuery是如何具有大量函数特性,并且极易扩展的特性等等,要想了解需要对jQuery中原型链式关系进行后续分析。
二、关于jQuery.fn和jQuery.prototype
其实在jquery中jQuery.fn和jQuery.prototype是等价的,他们也是一个对象字面量
jQuery.fn = jQuery.prototype={对象字面量其实也是隐式的调用了new Object(),所以jQuery的原型对象其实也是Object.prototype
....
}
三、关于jquery选择器
jquery中经常用到选择器,例如$("#id").css()等等,观察这种形式,我们直观上自己实现的时候可能会是这样的形式,
jq = new $("#id")
jq.css()
但是jquery的选择器使用的时候并不需要用户去实例化jquery对象,并没有new关键词。其实jquery利用了闭包的方式,在$("#id")函数调用的时候,内部会调用new去实例化另一个函数对象。看起来可能是这个样子
window.$ = window.jQuery=function(){
return new some_function();
}
闭包就是为了免除用户去写 new jQuery,那么你里面为什么是some_function而不是jQuery,这是因为外面已经是jQuery了,如果里面也是jQuery,会造成死循环调用,导致栈溢出。
上面的思路否决了,some_function到底是什么呢?jQuery拥有的那么多方法是放在哪里的?
因为jQuery是一个函数对象,如果在里面添加一些方法是可以的,然后some_function.prototype=jQuery这样可以吗?实际上,如果只是要实现选择器的功能是可以的,代码可能如下:
window.$ = window.jQuery= function(){
}
window.jQuery.max = function(){
}
window.jQuery.map = function(data,index){
}
但是jquery并没有像上面的代码这样做,jquery写了一个字面量对象fn,它里面包含了各种函数,例如each和map、grep等等,这样让选择器和jQuery本身独立开来,这样以来我们很容易能够定义一些全局的函数,例如常用的$.post, $.get,$.getJSON,$.min等等。
既然用字面量对象fn的方式是很有好处的,那么是不是some_function的prototype指向这个字面量对象fn就可以,其实确实是可以的,不过jquery就不是随便指定的some_function,而是在字面量对象fn中放置了一个init函数,并且 设置了jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
这样保证了通过$("#id")取得的init的实例也拥有了fn的大量函数和特性,并且代码更加简洁(不需要增加一个和fn和jquery本身没有关系的some_function)。
四、进一步的思考
其实,可能了解了这些会思考,为什么一定要设置jQuery.prototype = fn字面量对象,设置jQuery.fn = (fn字面量)对象就足够了啊?
其实确实只要Init的prototype是fn字面量对象就满足了选择器始终拥有fn的大量函数和特性。其实在jQuery中其实从始至终在选择器使用上也好,在一边的jQuery.max类似的函数调用也好,都没有实例化jQuery对象,在选择器使用的时候也只是实例化了jQuery.fn.init这样使得实例化速度很快(因为jQuery函数很大因为随着功能的增多)。对于为什么要jQuery.fn = jQuery.prototype = fn对象字面量,确实是一个值得思考的问题?其实应该反过来想,jQuery.prototype是定义的字面量,init.prototype = jQuery.prototype,这样就可以达到选择器所有需要的功能,但是每次如果扩展函数和方法都要写很长的”prototype“会不显得不美观,为了简洁,引入了.fn别名。这样一切就顺理成章了。
五、建议
去官网http://jquery.com/下载一份Jquery.js来阅读,肯定会收益匪浅。
更多相关文章
- 将JavaScript对象作为Dictionary 传递给C#WCF服务
- 通过],[和创建json对象来分割字符串
- jQuery循环没有每个和回调函数
- 我通过jQuery-ajax创建了__PHP_Incomplete_Class对象此错误
- 如何从Python脚本向jQuery发送JSON对象?
- JavaScript函数中的Ruby代码
- jQuery 事件绑定方法(bind hover toggle live.... )、删除事件方法
- jQuery:在对象内使用.remove()而不是Regex
- ajax回调json数组对象,jquery中$.each()循环解析