Zerlinda's Blog

jQuery插件机制:$.extend()、$.fn.extend() 及;(function($){….})()详解

一、$.extend(object)

$.extend(object) 是jQuery的的扩展方法,有一些重载原型。 简单来讲,$.extend(object)主要有以下三方面的使用方法。

1、合并多个对象。

extend(src1,src2,src3...);

它将src1,src2,src3…合并到src1中并返回src1。但是通过该方法合并,破坏了src1的结构。如果不想修改src1结构,可以像下面这样写:

extend({},src1,src2,src3...);

这样就可以将src1,src2,src3…进行合并,并且将合并结果返回。 例如:

var result=$.extend({},{a:"Tom",age:21},{name:"Jerry",sex:"Boy"})

那么合并后的结果是这样:

result={name:"Jerry",age:21,sex:"Boy"}

也就是说,如果存在相同的参数,后面的会覆盖掉前面的参数。 这个重载的方法,我们一般用来在编写插件时用自定义插件参数去覆盖插件的默认参数。

2、深度嵌套对象(深度拷贝)extend(boolean, src1,src2,src3…)

参数boolean代表是否进行深度拷贝。

通过一个例子来看什么是深度拷贝:

var src1 ={ name: "Tom", Info: {city: "Shanghai", sex: “male”} };
var src2 ={ name: "Cat", lnfo: {city: "Beijing", county:"China"} }
var result=$.extend( true, {}, src1, src2 );

src1中嵌套子对象Info: {city: "Shanghai", sex: “male”},src2中也嵌套子对象lnfo: {city: "Beijing", county:"China"},如果第一个深度拷贝参数为true,那么合并后的结果就是:

result={name:"Cat”, lnfo:{city:"Beijing", county:"China", sex:”male”}}

也就是说它会将src中的嵌套子对象也进行合并,而如果第一个参数boolean为false,合并结果如下:

result={name:"Cat", lnfo: {city: "Beijing", county:"China"} }

3、为JQuery 添加新方法(静态方法) $.extend({ fun1: function () { … } }); 该方法就是将fun1方法添加到jQuery的全局对象中去,如:

$.extend({
  sayHello:function(){alert('hello');}
});

调用的时候像下面这样: $.sayHello(); 但是要记住,通过$.extend({ fun1: function () { … } });添加的仅仅是一个静态方法。只能被jQuery对象调用。

二、$.fn.extend(object)

上边提到的上边提到的$.extend(object)为JQuery类添加了静态方法,即jQuery对象拥有这个方法。虽然你可以$.sayHello()调用该方法,但是具体的实例化对象却不能。jQuery提供了另一个方法为每一个实例添加一个实例方法:jQuery.fn.extend(object) 。 看一下jQuery.fn的源码:

jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {.....};
};

可以看出,jQuery.fn = jQuery.prototype,也就是jQuery对象的原型。所以jQuery.fn.extend()方法就是扩展jQuery对象的原型方法。我们知道对原型扩展的方法,是被该类的所有实例对象所共有的,那么所有的实例对象都可以使用我们扩展的这个方法。 例如在上个例子中,我们可以这样写来扩展jQuery原型的方法:

$.fn.extend({
  sayHello:function(){alert('hello');}
});

所以每个实例化对象可以直接通过这样调用: $(selector).sayHello(); 很方便对吧? 通过以上的介绍,你大概已经对:$.extend()方法和$.fn.extend()有了比较系统的了解了,那么如何使用他们来写自己的插件呢。首先来介绍第一步:

三、;(function($){….})(jQuery, window, document, undified)

平时在使用jQuery插件的时间,研究其源码会发现这一句总是必不可少。对于初学者真的很难搞明白这句代码的原理,查阅了资料才对其有些深入的了解:

首先,形如(function() {})();的函数叫做自执行的匿名函数/闭包。

这种形式的函数要与function() {}();区别开:function { })是表达式, function() {}是函数声明。 js在"预编译"阶段, 会解析函数声明, 但却忽略表式。当js执行到function() {}();时, 没有被调用的函数并不会被执行, 所以js会跳过function(){}去执行();。所以想一下,仅仅运行()这样肯定会报错; 而当js执行到(function {})();时, 由于(function {})是表达式, 按照优先级从左到右,于是第一个括号内的函数被强制执行,同时第二个括号内的参数也作为实参传入函数。 简而言之,第一个括号表示定义了一个匿名函数,然后第二个括号表示为该函数传递的参数。

然后是其它几点需要注意的: 代码最前面的分号,可以防止多个文件压缩合并后引起的语法错误。

匿名函数用圆括号强制执行的同时,也避免了函数体内的变量和外部变量冲突。

实参jQuery($)接受jQuery对象,也是为了避免jQuery变量冲突,保证插件可以正常运行。

其它window和document分别接受window和document对象,但在函数体内,window和document不再是全局变量而是局部变量。从提高性能方面来讲,减少了对全局变量的访问,非常有必要。如果插件中没有涉及到这两个对象则可省略。

Undefined是js考虑到兼容性所以增加一个形参,不赘述了。

另外,;(function($){….})()这种方法执行其中的代码时,Dom对象并不一定加载完毕。与此相反的是$(function(){}),这种方法在页面的Dom对象加载完后执行其中的函数。完整的写法便是我们熟悉的:$(document).ready(function(){});

发表评论

电子邮件地址不会被公开。 必填项已用*标注