var o1 = { name:'o1' };
var M = function(name){ this.name = name; }; var o2 = new M('o2');
Object.create()
方法建立一個新對象,使用現有的對象來提供新建立的對象的__proto__。 )
var P = {name:'o3'}; var o3 = Object.create(P);
二,原型鏈css
Object.getPrototypeOf(Object.prototype) //null
Object.prototype === Object.getPrototypeOf( {} ); //true
看下圖html
三,instanceof原理node
// 判斷實例對象的proto屬性和構造函數的prototype是否同一個地址 // 只要在原型鏈上的構造函數,都會被instanceof認爲是實例的構造函數 var M = function(name) { this.name = name; }; var o2 = new M('o2'); o2.__proto__ === M.prototype //true M.prototype.__proto__ === Object.prototype //true o2.__proto__.__proto__ === Object.prototype //true o2 instanceof M //true o2 instanceof Object //true // 用constructor屬性判斷更嚴謹 o2.__proto__.constructor === M //true o2.__proto__.constructor === Object //false
四,new運算符工做原理jquery
// new運算符及背後工做原理 new後跟構造函數 // 1,一個新對象被建立,它繼承自func.prototype(構造函數的原型對象) // 2,構造函數func被執行,執行的時候,相應的傳參會被傳入,同時上下文(this)會被指定爲這個新實例 // 3,若是構造函數返回了一個「對象」,那麼這個對象會取代整個new出來的結果,若是構造函數沒有返回對象,那麼new出來的結果爲步驟1建立的對象 var new2 = function(func) { var o = Object.create(func.prototype); var k = func.call(o); if (typeof k === 'object' && k != null) { return k; } else { return o; } };
五,原型鏈繼承的例子數組
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>proto</title> </head> <body> <div id="div1">123</div> <script> // 封裝DOM查詢 function Elem(id) { this.elem = document.getElementById(id); } Elem.prototype.html = function(val) { var elem = this.elem; if (val) { elem.innerHTML = val; return this;//方便鏈式操做 } else { return elem.innerHTML; } } Elem.prototype.on = function(type, fn) { var elem = this.elem; elem.addEventListener(type, fn); return this;//方便鏈式操做 } var div1 = new Elem('div1'); console.log(div1.html()); div1.html('<p>234p</p>').on('click', function() { alert('1'); }).html('<p>js</p>'); </script> </body> </html>
六:原型實際應用dom
1,看一個平時使用jquery或者zepto的例子:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jquery</title> </head> <body> <p>jquery 1</p> <p>jquery 2</p> <p>jquery 3</p> <div id="div1"> <p>jquery test in div</p> </div> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> var $p = $('p'); $p.css('color', 'red'); //css是原型方法 console.log($p.html()); //html是原型方法,這裏只打印第一個 jquery 1 var $div = $('#div1'); $div.find('p').css('color', 'blue'); //find,css是原型方法 console.log($div.html()); //html是原型方法 <p style="color: blue;">jquery test in div</p> </script> </body> </html>
(function(window) { // 空對象 var zepto = {}; // 構造函數 function Z(dom, selector) { var i, len = dom ? dom.length : 0; for (i = 0; i < len; i++) { this[i] = dom[i]; } this.length = len; this.selector = selector || ''; } zepto.Z = function(dom, selector) { // 注意,出現了 new 關鍵字 return new Z(dom, selector); } zepto.init = function(selector) { // 源碼中,這裏的處理狀況比較複雜,但由於本次只針對原型,所以這裏就弱化了 var slice = Array.prototype.slice; var dom = slice.call(document.querySelectorAll(selector)); return zepto.Z(dom, selector); } // 使用zepto的$ var $ = function(selector) { return zepto.init(selector); } window.$ = $; $.fn = { constructor: zepto.Z, css: function(key, value) { console.log('css'); }, html: function(value) { // console.log('html'); return '這是一個模擬的html函數'; } } zepto.Z.prototype = Z.prototype = $.fn; //!!! })(window)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>zepto</title> </head> <body> <p>zepto 1</p> <p>zepto 2</p> <p>zepto 3</p> <div id="div1"> <p>zepto test in div</p> </div> <script src="./my-zepto.js"></script> <script> var $p = $('p'); $p.css('color', 'red'); //css是原型方法 console.log($p.html()); //html是原型方法,這是一個模擬的html函數" </script> </body> </html>
(function(window) { var jQuery = function(selector) { // 注意new關鍵字,第一步就找到了構造函數 return new jQuery.fn.init(selector); } window.$ = jQuery; // 初始化 jQuery.fn jQuery.fn = jQuery.prototype = { //!!! constructor: jQuery, // 其餘函數 css: function(key, value) { }, html: function(value) { return 'html'; } } // 定義構造函數-簡化版 var init = jQuery.fn.init = function(selector) { var slice = Array.prototype.slice; var dom = slice.call(document.querySelectorAll(selector)); var i, len = dom ? dom.length : 0; for (i = 0; i < len; i++) { this[i] = dom[i]; } this.length = len; this.selector = selector || ''; } // 定義原型 init.prototype = jQuery.fn; })(window)
測試:新建jquery.html函數
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jquery</title> </head> <body> <p>jquery 1</p> <p>jquery 2</p> <p>jquery 3</p> <div id="div1"> <p>jquery test in div</p> </div> <script src="./my-jquery.js"></script> <script> var $p = $('p'); $p.css('color', 'red'); //css是原型方法 console.log($p.html()); //html是原型方法,這裏只打印第一個 "jquery 1" </script> </body> </html>
$.fn.getNodeName = function(){ return this[0].nodeName; }
好處:測試
1,只有$會暴露在window全局變量
2,將插件擴展統一到 $.fn.xxx 這一個接口,方便使用ui
實踐:this
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jquery</title> </head> <body> <p>jquery 1</p> <p>jquery 2</p> <p>jquery 3</p> <div id="div1"> <p>jquery test in div</p> </div> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> // 插件擴展 $.fn.getNodeName = function(){ // console.log(this); console.log(this[0].nodeName); } </script> <script> // 驗證 var $p = $('p'); $p.getNodeName() //P $div1 = $('#div1'); $div1.getNodeName() //DIV </script> </body> </html>