今天來實現一個簡單的js框架,相似jq的功能,實現了增減class,增減屬性,鏈式調用,合併對象等功能,html
更加深刻理解下js原型prototype
的應用,是以前承諾的原型模式應用的文章,歡迎評論交流vue
(function(window, document) { 'use strict'; // jq函數 var myJquery = function(selector){ return myJquery.fn.init(selector); } // 原型方法 myJquery.fn = myJquery.prototype = { // 修復原型鏈 constructor: myJquery, // 初始化方法 init: function(selector) { if(!selector) return; var el = document.querySelectorAll(selector); el = Array.from(el); // 設置原型 Object.setPrototypeOf(el,this); return el; } } // 將業務代碼註冊到全局命名空間 window.myJquery = window.$ = myJquery; })(window, document);
根據代碼,能夠看到首先,一個匿名自執行函數,而後在window上註冊,而後就是原型上添加init方法,這是個常規操做了;es6
這裏我沒按照jq來,爲了便於理解,我分紅了三個方法設計模式
myJquery.fn = myJquery.prototype = { // 得到屬性 getAttr: function(attr) { var i = 0, length = this.length; if(length === 0) return; if( length === 1){ return this[0].getAttribute(attr); } var arr = []; // 遍歷 for (; i < length; i++) { arr.push(this[i].getAttribute(attr)); } return arr; }, // 設置屬性 setAttr: function(attr,value) { var i = 0, length = this.length; if( length === 0) return; // 單一屬性時候 if(typeof attr === 'string' && value !== undefined){ for (; i < length; i++) { this[i].setAttribute(attr,value); } } // 是對象時候 if(typeof attr === 'object'){ for (var key in attr) { if (attr.hasOwnProperty(key)) { for (var j = 0; j < length; j++) { this[j].setAttribute(key,attr[key]); } } } } return this; }, // 刪除屬性 removeAttr: function(attr) { var i = 0, length = this.length; if(length === 0) return; for (; i < length; i++) { this[i].removeAttribute(attr); } return this; } }
主要仍是要判斷多種狀況,擴展自定義框架的功能,讓框架功能更增強大,我這考慮🤔了幾種狀況,不一樣的參數類型,固然可能沒有jq那麼完善了,不過看看也便於理解框架了。api
每一個框架都會有的,我這作了一個合併對象的功能,擴展框架的沒加,不過思路也是同樣的框架
// 合併對象 myJquery.extend = myJquery.fn.extend = function() { var i = 0, deep = arguments[0] || {}, _obj = {}, length = arguments.length; // 淺拷貝 if(typeof deep === 'object'){ [...arguments].forEach(val=>{ if(typeof val === 'object'){ Object.assign(_obj,val); } }); return _obj; } // 深拷貝 if(typeof deep === 'boolean'){ [...arguments].forEach(val=>{ if(typeof val === 'object'){ Object.assign(_obj,JSON.parse(JSON.stringify(val))); } }); return _obj; } }
下面是總體的代碼,這個簡單框架實現了添加刪除屬性,加減class,等等內容,後續,拓展代碼也是這樣加,這是對js原型模式基本應用函數
// 原生js實現框架 (function(window, document) { 'use strict'; // jq函數 var myJquery = function(selector){ return myJquery.fn.init(selector); } // 原型方法 myJquery.fn = myJquery.prototype = { // 修復原型鏈 constructor: myJquery, // 初始化方法 init: function(selector) { if(!selector) return; var el = document.querySelectorAll(selector); el = Array.from(el); // 設置原型 Object.setPrototypeOf(el,this); return el; }, // 得到屬性 getAttr: function(attr) { var i = 0, length = this.length; if(length === 0) return; if( length === 1){ return this[0].getAttribute(attr); } var arr = []; // 遍歷 for (; i < length; i++) { arr.push(this[i].getAttribute(attr)); } return arr; }, // 設置屬性 setAttr: function(attr,value) { var i = 0, length = this.length; if( length === 0) return; // 單一屬性時候 if(typeof attr === 'string' && value !== undefined){ for (; i < length; i++) { this[i].setAttribute(attr,value); } } // 是對象時候 if(typeof attr === 'object'){ for (var key in attr) { if (attr.hasOwnProperty(key)) { for (var j = 0; j < length; j++) { this[j].setAttribute(key,attr[key]); } } } } return this; }, // 刪除屬性 removeAttr: function(attr) { var i = 0, length = this.length; if(length === 0) return; for (; i < length; i++) { this[i].removeAttribute(attr); } return this; }, // 添加內容 html: function(val) { var i = 0, length = this.length; if(length === 0 || val === undefined) return; for(;i<length;i++){ this[i].innerHTML = val; } return this; }, // 添加class addClass: function(clsName) { var i = 0, length = this.length; if(length === 0 || clsName === undefined) return; for(; i < length; i++){ var cla = this[i].className; cla += " " + clsName; this[i].className = cla.trim(); } return this; }, // 刪除class removeClass: function(clsName) { var i = 0, length = this.length; if(length === 0 || clsName === undefined) return; var clsName = clsName.split(" "); for(; i<length; i++){ var cla = this[i].className; cla = cla.split(" "); // 爲了簡潔,用了點es6代碼 clsName.forEach(val=>{ cla = cla.filter(value=>value !== val); }); cla = cla.join(' ').trim(); this[i].className = cla; } return this; }, } // 合併對象 myJquery.extend = myJquery.fn.extend = function() { var i = 0, deep = arguments[0] || {}, _obj = {}, length = arguments.length; // 淺拷貝 if(typeof deep === 'object'){ [...arguments].forEach(val=>{ if(typeof val === 'object'){ Object.assign(_obj,val); } }); return _obj; } // 深拷貝 if(typeof deep === 'boolean'){ [...arguments].forEach(val=>{ if(typeof val === 'object'){ Object.assign(_obj,JSON.parse(JSON.stringify(val))); } }); return _obj; } } // 將業務代碼註冊到全局命名空間 window.myJquery = window.$ = myJquery; })(window, document);
js框架,都很好的運用了prototype
原型,這是js開發中必需要掌握的內容,這篇文章是原型模式的應用,但願對各位看官有所啓發,this
接下來,我看看出幾篇vue的文章,再試着作個vue的簡單實現,vue的話主要運用了設計模式的觀察者模式,主要用了Object.defineProperty
這個ES6的api,prototype
固然這篇文章就很少講了,但願你們看了有收穫,謝謝你們觀看😄!設計