jQuery插件扩展分析
jQuery对象简介
在源码中看到jQuery对象其实就是第一个函数表达式,这个函数里面什么都没有干,直接返回了一个init实例化的对象,由于init的原型对象引用指向的就是jQuery,所以这个对象实际就是jQuery的实例。
jQuery = function( selector, context ) {
//创建jQuery实例
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.fn.init( selector, context );
},
...
//jQuery的原型引用传递给jQuery.fn
jQuery.fn = jQuery.prototype
...
// Give the init function the jQuery prototype for later instantiation
//将jQuery原型引用传递给init
init.prototype = jQuery.fn;经过两次引用传递,init对象就具有jQuery对象的功能了,各个原型之间的关系参考下图:

JavaScript的原型分析可以参考前面的《理解JavaScript原型模式》。
将jquery.js引入文档之后,执行jQuery匿名函数的时候传递了window对象,把jQuery与$变量赋值给window,所以这两者通用的,都表示jQuery的实例化对象。我们代码里面就可以用jQuery.ajax(),jQuery.each()等原型中的方法了。
jQuery两种添加插件方式
jQuery里面有两种扩展可以实现自己的插件,一种是$.extend,另一种就是$.fn.extend,源代码里面它们其实指向同一个函数:
jQuery.extend = jQuery.fn.extend = function() {
var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},//返回的目标对象
i = 1,
length = arguments.length,
deep = false;
......
}从前面的分析大概就明白这两者的区别了,$.extend表示第一次加载进来的实例就添加一个extend函数,而$.fn.extend表示jQuery原型对象上面添加一个extend函数,所以在$.extend里面添加扩展函数可以直接用$.函数名()直接使用,而$.fn.extend需要执行$(选择器).函数名()实例化之后才可以调用扩展函数。可以简单的理解为,$.extend为jQuery全局对象添加方法,$.fn.extend为jQuery实例化添加方法。
$.extend方式添加插件
如果只添加一个参数相当于直接在jquery对象增加了一个属性,如果是多个参数,那么会合并到第一个参数,如:
1、直接添加对象属性为函数
1 | var t1 = $.extend({ |
这种方式就直接在jQuery全局对象上添加的函数。
2、另外一种就是拷贝对象
深拷贝,只要对象里面还有对象,会递归的去复制到目标对象,并把以前的值覆盖掉
1 | var child = {name: 'small', age: 1}; |
输出结果,:
1 | //child的属性值全部被覆盖 |
浅拷贝对象里面不嵌套的拷贝,如:
1 | var t3 = $.extend({'realname':'hello', 'password': 111111}, {'password':'222222'}); |
输入结果
1 | Object {realname: "hello", password: "222222"} |
这种参数扩展非常有用,在jquery插件中常常会用到默认有哪些参数值,然后用户调用的时候可以重写这些参数值,也可以增加额外的参数。
$.fn.extend方式添加插件
前面已经介绍了,$.fn.extend与$.extend指向的是同一个函数,所以两者的功能是一样的,$.fn.extend只是针对原型对象的。写一个简单的扩展就明白了:
1 | $.fn.extend({ |
如果想支持链式调用,可以在自定义的函数里面return一个jquery原型对象就可以了。如下所示:
1 | $.fn.extend({ |
由于extend函数里面就是把传入的属性赋值给当前对象(jQuery实例或者jQuery原型对象),所以如果只是一个函数扩展的话,也可以直接这样定义:
1 | $.fn.foo = function() { |
自定义插件标准
上面两种插件方式都是以直接传入参数形式进行扩展的,既然是扩展就应该遵守开闭原则,只对外就行修改,并且不能与原对象造成影响。所以自定义插件应该封装成一个类与外界保持独立,JavaScript虽然没有类但是有命名空间,可以为插件定义一个私有化空间,目前一般都采用匿名函数来定义,如:
1 | (function($){ |
可以看到匿名函数传入了jQuery对象,内部函数就可以共享jQuery的很多功能了,所以一般引入其他插件,有一个前提就是必须先引用jquery.js再引用插件的js文件。
