摘要:動態原型模式是由構造函數和原型模式組合而成的,那么構造函數是怎樣的呢這是一個典型的構造函數,通過使用函數,實例化一個對象,那么為什么可以通過使用操作符實例化對象呢,其實在使用操作符的同時,系統會執行以下操作執行函數代碼首先默認生成一個對象,
動態原型模式是由構造函數和原型模式組合而成的,那么構造函數是怎樣的呢:
function Box(name){ this.name = name; this.call = function(){ alert("your name is "+ this.name) } } var box = new Box("obama");
這是一個典型的構造函數,通過使用new函數,實例化一個box對象,那么為什么可以通過使用new操作符實例化對象呢,其實在使用new操作符的同時,系統會執行以下操作;
var box = new Object(); box.__proto__ = Box.prototype; Box.call(box); //執行函數代碼 return box;
首先默認生成一個對象,繼承構造函數Box的原型,然后把函數的作用域綁定在這個對象上,在執行函數,最后返回這個對象,因此每個實例對象都是一個獨立的對象,我們知道每個對象都是不相等的;
var box1 = new Box("a"); var box2 = new box("a"); box1.call == box2.call //false
原型模式中,
function Bar(){}; Bar.prototype = { constructor:Box, age:100, call:function(){ alert("your age is" + this.age) } }
我們都知道使用字面量的寫法,會默認生成Object對象,因此要強制把constructor屬性指向Bar,執行的過程是先看自身有沒有這個屬性,有就執行,不管原型里是否還有,如果沒有就繼續查找原型,有就執行,沒有就報錯,如何判斷是自身屬性還是原型里的屬性呢;
var bar = new Bar(); bar.name = "obama"; bar.hasOwnProperty("name"); //true //hasOwnProperty 只會判斷自身是否有這個屬性,原型是否有無法判斷; "name" in bar; //true // in這個方法更近一步能判斷不管自身還是原型有屬性(當然是可以枚舉的屬性) //通過這兩個方法我們可以判斷原型中是否有屬性 function isProperty(object,property){ return !object.hasOwnProperty(property) && (property in object); }
重點!!原型是會重寫的,這和JS里其他的對象一樣,后面的會覆蓋前面的,還有個問題是如果原型中修改屬性,一個實例對象就會改寫這個值,導致其他的實例對象都會改變!!
function Box(){ } Box.prototype = { constructor:Box, boxs:["box1","box2","box3"], name:"bigBox" } var box1 = new Box(); var box2 = new Box(); box1.name = "first box"; console.log(box1.name); //"first box" console.log(box2.name); //"bigbox" box1.boxs.push("box4"); console.log(box1.boxs); //["box1", "box2", "box3", "box4"] console.log(box2.boxs); //["box1", "box2", "box3", "box4"]
很難理解為什么box1修改name屬性就不會重寫原型,而修改boxs屬性就會重寫原型,兩者的差別就在于一個是賦值,一個是查找,打個比方,
a向b借了100元,那么a就得到了100元,不是a的父親,爺爺得到了100元,所以賦值即給a添加不論是屬性還是方法收益的只有a,不會給a的父親,爺爺其他人也賦值,但是如果b找a 還的話,如果找不到a就可以找a 的父親爺爺等其他人,這個意思是是說,只要是賦值,就只作用在賦值對象上,但是查找就不同,可以一直追溯到其他人,上面的例子,
box1.boxs.push(""box4"),可以這么理解,首先是查找,box1.boxs,不然如何push呢,自身屬性沒有,但是原型上有,有就OK直接操作push,但是這個操作是對象是所有對象共享的,所以一旦修改就改變了!
基于以上的問題,那么動態原型模式就是把共享的使用原型,不共享的使用構造函數,
function Box(){ this.name:"bigBox"; this.boxs = ["box1", "box2", "box3"]; }; Box.prototype = { constructor:Box, num:function(){ console.log(this.boxs.length); } } //或者寫在一起 function Box(){ this.name:"bigBox", this.boxs = ["box1", "box2", "box3"]; if(typeof this.run != "function"){ Box.prototype.num = function(){ console.log(this.boxs.length); } } } //因為構造函數執行時,里面的代碼都會執行一遍,而原型有一個就行,不用每次都重復,所以僅在第一執行時生成一個原型,后面執行就不必在生成,所以就不會執行if包裹的函數, //其次為什么不能再使用字面量的寫法,我們都知道,使用構造函數其實是把new出來的對象作用域綁定在構造函數上,而字面量的寫法,會重新生成一個新對象,就切斷了兩者的聯系!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85111.html
摘要:可能因為先入為主,在編程之中,往往不由自主地以的邏輯編程思路設計模式進行開發。這是原型模式很重要的一條原則。關于閉包與內存泄露的問題,請移步原型模式閉包與高階函數應該可以說是設計模式的基礎要領吧。在下一章,再分享一下的幾種常用設計模式。 前 在學習使用Javascript之前,我的程序猿生涯里面僅有接觸的編程語言是C#跟Java——忽略當年在大學補考了N次的C與VB。 從靜態編程語言,...
摘要:概括創建自定義類型的最常見方式,就是組合使用構造函數模式與原型模式。應用方式一分開定義,用來理解構造函數與原型方式二動態原型模式定義,避免獨立的構造函數和原型,更完美的定義形式。 概括:創建自定義類型的最常見方式,就是組合使用構造函數模式與原型模式。 好處:通過這種方式,不僅每個實例都有自己的一份實例屬性的副本,而且同時又共享著對方法的引用,最大限度的節省了內存。而且這種混合模式還支...
摘要:組合使用構造函數模式和原型模式創建自定義類型的最常見方式,就是組合使用構造函數模式與原型模式。也就是說,寄生構造函數模式下,構造函數創建的對象與在構造函數外創建的對象沒有什么不同。 前言 最近在細讀Javascript高級程序設計,對于我而言,中文版,書中很多地方翻譯的差強人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內容引用自《JavaScri...
摘要:通過這種操作,就有了構造函數的原型對象里的方法。你也看到了,就是一個普通對象,所以這種寄生式繼承適合于根據已有對象創建一個加強版的對象,在主要考慮通過已有對象來繼承而不是構造函數的情況下,這種方式的確很方便。 原文地址在我的博客, 轉載請注明出處,謝謝! 標簽: [es5對象、原型, 原型鏈, 繼承] 注意(這篇文章特別長)這篇文章僅僅是我個人對于JavaScript對象的理解,并不是...
閱讀 2508·2023-04-25 19:31
閱讀 2244·2021-11-04 16:11
閱讀 2811·2021-10-08 10:05
閱讀 1520·2021-09-30 09:48
閱讀 2319·2019-08-30 15:56
閱讀 2414·2019-08-30 15:56
閱讀 2177·2019-08-30 15:53
閱讀 2272·2019-08-30 15:44