摘要:構成類數組對象,引入,并使其自增版本信息模擬數組,即這里構成一個類數組對象由于這里把作為構造函數調用,得到一個對象,所以我們把作為的原型。
本文簡單實現jQuery框架,深入理解javascript對象。
本文的對照版本是jQuery-1.2.6.js
本文注重jquery結構設計思路,并不側重具體功能的實現以及兼容性和安全性的部分。
首先建立基本框架如下:
(function(window){ "use strict"; var jQuery = window.jQuery = window.$ = function(selector){ //定義$函數,并把$和jQuery暴露到外面 }; jQuery.fn = jQuery.prototype = { //jQuery原型 }; jQuery.extend = jQuery.fn.extend = function(){ //添加擴展方法,jQuery.extend添加靜態方法,也可以實現繼承,jQuery.fn.extend添加動態方法 } })(window);
進一步,實現jQuery的初始化
//上述框架中的部分代碼 //由于$("#selector")得到的是一個jQuery對象,嘗試直接返回jQuery對象 var jQuery = window.jQuery = window.$ = function(selector){ return new jQuery(); //這里會導致一個死循環,所以不能這樣直接構建jQuery對象 };
修正上述代碼中的死循環,我們可以試圖返回this,但是this明顯是window,不是我們需要的jQuery,利用原型中的this返回構造函數實例化對象的特點(不理解的可以參看javascript中this詳解),我們作以下修改:
//上述框架中的部分代碼 //由于$("#selector")得到的是一個jQuery對象,嘗試直接返回jQuery對象 var jQuery = window.jQuery = window.$ = function(){ return jQuery.fn.init(); //執行初始化 }; jQuery.fn = jQuery.prototype = { init: function(){ return this; }, jQuery: "1.0.0", //jQuery版本信息 length: 0, //模擬數組,即這里構成一個類數組對象 size: function(){ return this.length; } }
到此$()可以返回一個jQuery對象了。但是在舊瀏覽器中有一個bug。如果用戶如下這樣使用代碼,那么什么都得不到:
var ele = $.fn.init();
這里直接調用了init(), 這樣會得到init創造的對象,由于$是個函數,$.fn是函數的原型,函數原型是個空函數,所以這里得到了一個以空函數為構造函數創造的對象。為了解決這問題,采用new的方式:
//上述框架中的部分代碼 var jQuery = window.jQuery = window.$ = function(selector){ return new jQuery.fn.init(selector); //執行初始化 }; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function(selector){ var elements = document.querySelectorAll(selector); //順便簡單的實現了選擇器 //注意querySelectorAll在老的瀏覽器中是不支持的,這里專注在jQuery的結構上。 Array.prototype.push.apply(this, elements); //構成類數組對象,引入length,并使其自增 return this; }, jQuery: "1.0.0", //jQuery版本信息 length: 0, //模擬數組,即這里構成一個類數組對象 size: function(){ return this.length; } } jQuery.fn.init.prototype = jQuery.fn;
由于這里把jQuery.fn.init()作為構造函數調用,得到一個jQuery對象,所以我們把jQuery.fn作為jQuery.fn.init()的原型。
下一步實現extend方法
//上述框架中的部分代碼 jQuery.extend = jQuery.fn.extend = function(obj, srcObj){ var target, len = arguments.length; if(len === 1){ //傳入一個參數時實現繼承 deep(obj, this); return this; } else { for(var i = 1; i < len; i++){ target = arguments[i]; deep(target, obj); } return obj; } function deep(oldOne, newOne){ //實現深拷貝 for(var prop in oldOne){ if(typeof oldOne[prop] === "object" && oldOne[prop] !== null){ newOne[prop] = oldOne[prop].constructor === Array ? [] : {}; deep(oldOne[prop], newOne[prop]); } else{ newOne[prop] = oldOne[prop]; } } } };
寫了extend,我們定義幾個簡單的方法(2靜態方法,3個動態方法)可以用來測試。
//添加靜態方法 jQuery.extend({ trim: function(text){ return (text || "").replace(/^s+|s+$/g, ""); }, makeArray: function(obj){ return Array.prototype.slice.call(obj); } }); //添加動態方法 jQuery.fn.extend({ //get方法 get: function(num){ return num == null ? jQuery.makeArray(this): num < 0 ? this[ num + this.length ] : this[ num ]; //索引小于零表示倒數 }, //each 遍歷執行函數 each: function(fun){ for(var i = 0, len = this.length; i < len; ++i){ if(fun(i, this[i]) === false) break; } return this; //用于鏈式調用 }, //修改css屬性 css: function(key, value){ var len = arguments.length; if(len === 1){ //傳入1個參數返回對應值 return this[0].style[key]; } else if(len === 2){ //傳入2個參數設置對應值 this.each(function(index, ele){ ele.style[key] = value; }); } return this; //用于鏈式調用 } });
到這里,jQuery的基本結構就形成了,還有一個問題需要解決,就是處理變量沖突。
當環境中以及有jQuery和$時可以選擇釋放$或時釋放jQuery和$
(function(window){ "use strict"; //在框架一開始先保留外部可能存在的$或jQuery變量,以便在后來恢復 var _$ = window.$; var _jQuery = window.jQuery; var jQuery = window.jQuery = window.$ = function(selector){}; jQuery.fn = jQuery.prototype = {}; jQuery.extend = jQuery.fn.extend = function(){}; })(window);
然后寫noConflict函數
jQuery.extend({ noConflict: function(deep){ //傳入true時同時釋放$和jQuery,否則只是釋放$ window.$ = _$; if(deep) window.jQuery = _jQuery; return jQuery; } });
到此為止,jQuery的框架已經形成。下面是完整代碼部分:
(function(window){ "use strict"; var _$ = window.$; var _jQuery = window.jQuery; //定義全局接口 var jQuery = window.jQuery = window.$ = function(selector){ return new jQuery.fn.init(selector); }; var HTMLRegex = /^(?:s*(<[wW]+>)[^>]*|#([w-]+))$/; //用于匹配html標簽 var rootjQuery; //默認根節點的jQuery對象 //原型 jQuery.fn = jQuery.prototype = { constructor: jQuery, // init: function(selector){ // var elements = document.getElementsByTagName(selector); // Array.prototype.push.apply(this, elements); // return this; // }, init: function(selector){ if(!selector){ return this; } var elements = document.getElementsByTagName(selector); Array.prototype.push.apply(this, elements); return this; }, jQuery: "1.0.0", length: 0, size: function(){ return this.length; } }; jQuery.fn.init.prototype = jQuery.fn; //繼承 jQuery.extend = jQuery.fn.extend = function(obj){ var target, len = arguments.length; if(len === 1){ //傳入一個參數時實現繼承 deep(obj, this); return this; } else { for(var i = 1; i < len; i++){ target = arguments[i]; deep(target, obj); } return obj; } function deep(oldOne, newOne){ for(var prop in oldOne){ if(typeof oldOne[prop] === "object" && oldOne[prop] !== null){ newOne[prop] = oldOne[prop].constructor === Array ? [] : {}; deep(oldOne[prop], newOne[prop]); } else{ newOne[prop] = oldOne[prop]; } } } }; //靜態函數 jQuery.extend({ trim: function(text){ return (text || "").replace(/^s+|s+$/g, ""); }, noConflict: function(deep){ window.$ = _$; if(deep) window.jQuery = _jQuery; return jQuery; }, makeArray: function(obj){ return Array.prototype.slice.call(obj); } }); //對象方法 jQuery.fn.extend({ get: function(num){ return num == null ? jQuery.makeArray(this): num < 0 ? this[ num + this.length ] : this[ num ]; //索引小于零表示倒數第n個 }, each: function(fun){ for(var i = 0, len = this.length; i < len; ++i){ if(fun(i, this[i]) === false) break; } return this; //用于鏈式調用 }, css: function(key, value){ var len = arguments.length; if(len === 1){ return this[0].style[key]; } else if(len === 2){ this.each(function(index, ele){ ele.style[key] = value; }); } return this; //用于鏈式調用 } }); }(window));
上述代碼源碼:Download
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97616.html
摘要:大潮來襲前端開發能做些什么去年谷歌和火狐針對提出了的標準,顧名思義,即的體驗方式,我們可以戴著頭顯享受沉浸式的網頁,新的標準讓我們可以使用語言來開發。 VR 大潮來襲 --- 前端開發能做些什么 去年谷歌和火狐針對 WebVR 提出了 WebVR API 的標準,顧名思義,WebVR 即 web + VR 的體驗方式,我們可以戴著頭顯享受沉浸式的網頁,新的 API 標準讓我們可以使用 ...
摘要:模塊化原理簡析的核心原理一切皆模塊在中,,靜態資源文件等都可以視作模塊便于管理,利于重復利用按需加載進行代碼分割,實現按需加載。模塊化原理以為例,分析構建的模塊化方式。 webpack模塊化原理簡析 1.webpack的核心原理 一切皆模塊:在webpack中,css,html.js,靜態資源文件等都可以視作模塊;便于管理,利于重復利用; 按需加載:進行代碼分割,實現按需加載。 2...
閱讀 2484·2023-04-25 19:24
閱讀 1700·2021-11-11 16:54
閱讀 2833·2021-11-08 13:19
閱讀 3547·2021-10-25 09:45
閱讀 2552·2021-09-13 10:24
閱讀 3276·2021-09-07 10:15
閱讀 4014·2021-09-07 10:14
閱讀 2950·2019-08-30 15:56