本文是參考了Joey的博客後整理的。css
先從一個簡單擴展jQuery對象的demo開始提及:html
//sample:擴展jquery對象的方法,redTextColor()用於改變字體顏色。
(function ($) { $.fn.extend({ "redTextColor": function () { // 默認字體顏色爲紅色
return this.css({ color: "red" }); } }); })(window.jQuery);
調用方式:jquery
$(function(){ $('p').redTextColor(); })
這是一個簡單的擴展,下面咱們開始詳細分析一下上面的代碼。ajax
爲了方便用戶建立插件,jQuery提供了jQuery.extend()和jQuery.fn.extend()兩種方法。bootstrap
jQuery.extend(object) ,一個參數的用於擴展jQuery類自己,也就是用來在jQuery類/命名空間上增長新函數,或者叫靜態方法,例如jQuery內置的 ajax方法都是用jQuery.ajax()這樣調用的,有點像 「類名.方法名」 靜態方法的調用方式。下面咱們也來寫個jQuery.extend(object)的例子:閉包
//擴展jQuery對象自己
jQuery.extend({ "minValue": function (a, b) { ///<summary>
/// 比較兩個值,返回最小值
///</summary>
return a < b ? a : b; }, "maxValue": function (a, b) { ///<summary>
/// 比較兩個值,返回最大值
///</summary>
return a > b ? a : b; } }); //調用
var i = 100; j = 101; var min_v = $.minValue(i, j); // min_v 等於 100
var max_v = $.maxValue(i, j); // max_v 等於 101
重載版本:jQuery.extend([deep], target, object1, [objectN])框架
用一個或多個其餘對象來擴展一個對象,返回被擴展的對象。
若是不指定target,則給jQuery命名空間自己進行擴展。這有助於插件做者爲jQuery增長新方法。
若是第一個參數設置爲true,則jQuery返回一個深層次的副本,遞歸地複製找到的任何對象。不然的話,副本會與原對象共享結構。
未定義的屬性將不會被複制,然而從對象的原型繼承的屬性將會被複制。
參數
deep: 可選。若是設爲true,則遞歸合併。
target: 待修改對象。
object1: 待合併到第一個對象的對象。
objectN: 可選。待合併到第一個對象的對象。dom
示例1:
合併 settings 和 options,修改並返回 settings。
函數
var settings = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; jQuery.extend(settings, options);
結果:
測試
settings == { validate: true, limit: 5, name: "bar" }
示例2:
合併 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" }
這個重載的方法,咱們通常用來在編寫插件時用自定義插件參數去覆蓋插件的默認參數。
jQuery.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類的實例可使用這個「成員函數」。jQuery.fn.extend(object)和jQuery.extend(object)方法必定要區分開來。
(1). 首先, 要清楚二者的區別: (function {// code})是表達式, function {// code}是函數聲明.
(2). 其次, js"預編譯"的特色: js在"預編譯"階段, 會解釋函數聲明, 但卻會忽略表式.
(3). 當js執行到function() {//code}();時, 因爲function() {//code}在"預編譯"階段已經被解釋過, js會跳過function(){//code}, 試圖去執行();, 故會報錯;
當js執行到(function {// code})();時, 因爲(function {// code})是表達式, js會去對它求解獲得返回值, 因爲返回值是一 個函數, 故而遇到();時, 便會被執行.
另外, 函數轉換爲表達式的方法並不必定要靠分組操做符(),咱們還能夠用void操做符,~操做符,!操做符……
例如:
bootstrap 框架中的插件寫法: !function($){ //do something; }(jQuery); 和 (function($){ //do something; })(jQuery); 是一回事。
匿名函數最大的用途是建立閉包(這是JavaScript語言的特性之一),而且還能夠構建命名空間,以減小全局變量的使用。
例如:
var a=1;
(function()(){
var a=100;
})();
alert(a); //彈出 1
更多 閉包和匿名函數 可查看 Javascript的匿名函數與自執行 這篇文章。
接下來咱們寫一個高亮的插件
1.定義一個閉包區域,防止插件污染
//這樣閉包能夠限制命名空間
(function($){ ...code... })(window.jQuery);
2.使用jQuery.fn.extend()的方式製做插件
(function ($) { $.fn.extend({ 'highlight': function (op) { ........ } }); })(window.jQuery);
3.設置默認參數,實現插件功能
(function ($) { $.fn.extend({ 'highlight': function (op) { var opt = $.extend({},defaults,op); this.each(function () { $(this).css({ backgroundColor: opt.background, color: opt.foreground }); }) } });
//默認參數 var defaults = { background: 'red', foreground: 'yellow' } })(window.jQuery);
至此,高亮插件已基本實現了,調用代碼以下:
$('p').highlight({ background: 'yellow', foreground: 'gray' });
這裏只能 直接調用,不能鏈式調用。咱們知道jQuey是能夠鏈式調用的,就是能夠在一個jQuery對象上調用多個方法,如:
$('p').css({marginTop:'100px'}).addAttr("title","測試「);
可是咱們上面的插件,就不能這樣鏈式調用了。好比:$("p").highLight().css({marginTop:'100px'}); //將會報找不到css方法,緣由在與個人自定義插件在完成功能後,沒有將 jQuery對象給返回出來。接下來,return jQuery對象,讓咱們的插件也支持鏈式調用。(其實很簡單,就是執行完咱們插件代碼的時候將jQuery對像return 出來,和上面的代碼沒啥區別)
(function ($) { $.fn.extend({ 'highlight': function (op) { //使用jQuery.extend 覆蓋插件默認參數 var opt = $.extend({},defaults,op); //這裏的this 就是 jQuery對象。這裏return 爲了支持鏈式調用 return this.each(function () { //根據參數來設置 dom的樣式 $(this).css({ backgroundColor: opt.background, color: opt.foreground }); }) } }); //默認參數 var defaults = { background: 'red', foreground: 'yellow' }; })(window.jQuery);
4.暴露公共方法 給別人來擴展你的插件(若是有需求的話)
好比的高亮插件有一個format方法來格式話高亮文本,則咱們可將它寫成公共的,暴露給插件使用者,不一樣的使用着根據本身的需求來重寫該format方法,從而是高亮文本能夠呈現不一樣的格式。
//公共的格式化 方法. 默認是加粗,用戶能夠經過覆蓋該方法達到不一樣的格式化效果。 $.fn.highLight.format = function (str) { return "<h3>" + str + "</h3>"; }
5.插件私有方法
有些時候,咱們的插件須要一些私有方法,不能被外界訪問。例如 咱們插件裏面須要有個方法 來檢測用戶調用插件時傳入的參數是否符合規範。
6.其餘的一些設置,如:爲你的插件加入元數據插件的支持將使其變得更強大。
完整的高亮插件代碼以下:
//閉包限定命名空間 (function ($) { $.fn.extend({ "highLight": function (options) { //檢測用戶傳進來的參數是否合法 if (!isValid(options)) return this; var opts = $.extend({}, defaluts, options); //使用jQuery.extend 覆蓋插件默認參數 return this.each(function () { //這裏的this 就是 jQuery對象。這裏return 爲了支持鏈式調用 //遍歷全部的要高亮的dom,當調用 highLight()插件的是一個集合的時候。 var $this = $(this); //獲取當前dom 的 jQuery對象,這裏的this是當前循環的dom //根據參數來設置 dom的樣式 $this.css({ backgroundColor: opts.background, color: opts.foreground }); //格式化高亮文本 var markup = $this.html(); markup = $.fn.highLight.format(markup); $this.html(markup); }); } }); //默認參數 var defaluts = { foreground: 'red', background: 'yellow' }; //公共的格式化 方法. 默認是加粗,用戶能夠經過覆蓋該方法達到不一樣的格式化效果。 $.fn.highLight.format = function (str) { return "<strong>" + str + "</strong>"; } //私有方法,檢測參數是否合法 function isValid(options) { return !options || (options && typeof options === "object") ? true : false; } })(window.jQuery);
調用:
//調用者覆蓋 插件暴露的共公方法 $.fn.highLight.format = function (txt) { return "<em>" + txt + "</em>" } $(function () { $("p").highLight({ foreground: 'orange', background: '#ccc' }); //調用自定義 高亮插件 });