一. jQuery的插件机制

为了方便用户创建插件,jquery提供了jQuery.extend()和jQuery.fn.extend()方法 jQuery.extend(object) ,一个参数的用于扩展jQuery类本身,也就是用来在jQuery类/命名空间上增加新函数,或者叫静态方法,例如jQuery内置的 ajax方法都是用jQuery.ajax()这样调用的,有点像 “类名.方法名” 静态方法的调用方式。

jQuery.extend() 扩展 //扩展jQuery对象本身
jQuery.extend({ "minValue": function (a, b) { return a < b ? a : b; }, "maxValue": function (a, b) { return a > b ? a : b; } }); var i = 100; j = 101; var min_v = $.minValue(i, j);

jQuery.extend()方法重载 jQuery.extend([deep], target, object1, [objectN])

参数 deep: 可选。如果设为true,则递归合并。 target: 待修改对象。 object1: 待合并到第一个对象的对象。 objectN: 可选。待合并到第一个对象的对象。

示例 合并 defaults 和 options, 不修改 defaults。 var empty = {}; var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; var settings = jQuery.extend(empty, defaults, options)

结果 settings == { validate: true, limit: 5, name: "bar" } empty == { validate: true, limit: 5, name: "bar" }

用一个或多个其他对象来扩展一个对象,返回被扩展的对象。 如果不指定target,则给jQuery命名空间本身进行扩展。这有助于插件作者为jQuery增加新方法。 如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 未定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制。 Query.fn.extend(object)扩展 jQuery 元素集来提供新的方法(常用来制作插件)。

首先我们来看fn 是什么东西呢。查看jQuery代码,就不难发现。 jQuery.fn = jQuery.prototype = {    init: function( selector, context ) {.....}; }; 原来 jQuery.fn = jQuery.prototype,也就是jQuery对象的原型。那jQuery.fn.extend()方法就是扩展jQuery对象的原型方法。我们知道扩展原型上的方法,就相当于为对象添加“成员方法”,类的“成员方法”要类的对象才能调用,所以使用jQuery.fn.extend(object)扩展的方法,jQuery类的实例可以使用这个“成员函数”,比如$(‘p’).extend(obj)。 jQuery.fn.extend(object)和jQuery.extend(object)方法一定要区分开来。 ** 二. 自执行的匿名函数/闭包 **

  1. 什么是自执行的匿名函数?
    它是指形如这样的函数: (function(){// code})();

  2. 疑问 为什么(function() {// code})();可以被执行, 而function() {// code}();却会报错?
    (1).首先,要清楚两者的区别:(function(){// code})是表达式,function(){// code}是函数声明.
    (2).其次, js"预编译"的特点: js在"预编译"阶段, 会解释函数声明, 但却会忽略表达式.
    (3).当js执行到function() {//code}();时, 由于function() {//code}在"预编译"阶段已经被解释过, js会跳过function(){//code}, 试图去执行();, 故会报错;
    当js执行到(function(){// code})();时, 由于(function(){// code})是表达式, js会去对它求解得到返回值, 由于返回值是一 个函数, 故而遇到();时, 便会被执行.

匿名函数最大的用途是创建闭包(这是JavaScript语言的特性之一),并且还可以构建命名空间,以减少全局变量的使用。

例如: var a=1; (function(){     var a=100;   })(); alert(a); //弹出 1 三. 分步封装JQuery插件

第一步定义一个闭包区域,防止插件“污染”。 (function($) {} )(window.jQuery);

第二步jQuery.fn.extend(object)扩展jquery方法制作插件 (function ($) { $.fn.plugin=function(options){ //do something
}; })(window.jQuery);

第三步给插件默认参数,实现插件的功能 (function ($) { $.fn.plugin=function (options) { var defaults={ foreground: 'red', background: 'yellow' }; //options合并到defaults上,defaults继承了options上的各种属性和方法,将所有的赋值给endOptions var endOptions=$.extend({},defaults,options); this.each(function () { var $this = $(this); $this.css({ backgroundColor: endOptions.background, color: endOptions.foreground }); }); return this; }; })(jQuery);

最后调用插件 $(function () { $("p").plugin({ foreground: 'orange', background: '#ccc' }); //调用自定义 插件 }); 注意

  1. 有一种东西叫脚本压缩,前端页面要减少脚本数量和脚本大小,所以要把一类的脚本压缩在一起,为了避免压缩时前一个脚本没有写最后一个分号而导致压缩后脚本不能使用,所以要在开始加一个分号。

  2. 函数全部放在闭包里,外面的函数就调用不到里面的参数了,比较安全。

  3. 之所以插件要return this,返回当前对象,是为了遵循jQuery的链式写法特点。 ** 总结**

  4. jQuery.fn = jQuery.prototype,也就是jQuery对象的原型。jQuery.fn.extend()方法就是扩展jQuery对象的原型方法。为对象添加“成员方法”,类的“成员方法”要类的对象才能调用,所以使用jQuery.fn.extend(object)扩展的方法,jQuery类的实例可以使用这个“成员函数”,比如$(‘p’).extend(obj)。

  5. 闭包可以构建命名空间,以减少全局变量的使用,避免全局污染。

  6. $.extend()多用来合并插件中的参数,也可以用来拓展全局函数,$.fn.extend()用来为对象添加成员方法。

  7. return this返回该对象,便于jQuery方法的链式调用。