我们经常用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来阅读,肯定会收益匪浅。


更多相关文章

  1. 将JavaScript对象作为Dictionary 传递给C#WCF服务
  2. 通过],[和创建json对象来分割字符串
  3. jQuery循环没有每个和回调函数
  4. 我通过jQuery-ajax创建了__PHP_Incomplete_Class对象此错误
  5. 如何从Python脚本向jQuery发送JSON对象?
  6. JavaScript函数中的Ruby代码
  7. jQuery 事件绑定方法(bind hover toggle live.... )、删除事件方法
  8. jQuery:在对象内使用.remove()而不是Regex
  9. ajax回调json数组对象,jquery中$.each()循环解析

随机推荐

  1. Android开发环境搭建
  2. widget(4、spinner)
  3. Android ApiDemos示例解析(140):Views->L
  4. Android 小的知识片
  5. 取消自动获取焦点(默认进来焦点到edittex
  6. android设置textview限制字数以省略号显
  7. android ListView嵌套checkbox并取代chec
  8. CheckBox组件的熟悉
  9. Android架构分析之Android开发环境搭建
  10. android 默认应用安装在sd卡中 (>2.2)