摘要:給添加屬性給的原型對象添加屬性原型鏈在中,每個對象都有一個屬性,其保存著的地址就構成了對象的原型鏈。實例變量實例函數原型鏈繼承有了原型鏈,就可以借助原型鏈實現繼承。是中唯一一個處理屬性但是不查找原型鏈的函數。
前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總
歡迎提issues斧正:原型&原型鏈&原型繼承
JavaScript-原型&原型鏈&原型繼承JavaScript的原型是一個重要的知識點,很多擴展應用都是從原型出發的。要說原型,我們先簡單說一下函數創建過程。上一篇文章用閉包實現類和繼承中用的是原型繼承,今天就講一講原型繼承。更多繼承在后面的文章中更新。
函數創建過程function Xzavier() {};
1.創建一個對象(有constructor屬性及[[Prototype]]屬性),其中[[Prototype]]屬性不可訪問、不可枚舉。
2.創建一個函數(有name、prototype屬性),再通過prototype屬性 引用第1步創建的對象。
3.創建變量Xzavier,同時把函數的引用賦值給變量Xzavier。
構造函數是用來新建同時初始化一個新對象的函數,所以,任何一個函數都可以是構造函數。只是我們在寫代碼的時候一般首字母大寫以便區分使用。
原型每個函數在創建的時候js都自動添加了prototype屬性,這就是函數的原型,原型就是函數的一個屬性,類似一個指針。原型在函數的創建過程中由js編譯器自動添加。
function Xzavier() { this.name = "xzavier"; this.sex = "boy"; this.job = "jser"; } //給A添加屬性 Xzavier.age = 23; //給A的原型對象添加屬性 Xzavier.prototype.sports = function() {console.log("basketball")} Xzavier.prototype = { hobbit1: function() {console.log("basketball");}, hobbit2: function() {console.log("running");} };原型鏈
在JavaScript中,每個對象都有一個[[Prototype]]屬性,其保存著的地址就構成了對象的原型鏈。
[[Prototype]]屬性是js編譯器在對象被創建時自動添加的,其取值由new運算符的右側參數決定。字面量的方式可轉化為new Obejct();
var x = new Xzavier(); vae o = {}; //var o = new Obejct();
通過對象的[[Prototype]]保存對另一個對象的引用,通過這個引用往上進行屬性的查找,這就是原型鏈查找機制。
對象在查找某個屬性的時候,會首先遍歷自身的屬性,如果沒有則會繼續查找[[Prototype]]引用的對象,如果再沒有則繼續查找[[Prototype]].[[Prototype]]引用的對象,依次類推,直到[[Prototype]].….[[Prototype]]為undefined
var str = new String("xzavier"); str
Object.prototype的[[Prototype]]就是undefined
function Xzavier() { this.name = "xzavier"; } var x = new Xzavier(); x.age = 23; console.log(x.job); // 獲取x的job屬性 undefined
1、遍歷x對象本身,結果x對象本身沒有job屬性
2、找到x的[[Prototype]],也就是其對應的對象Xzavier.prototype,同時進行遍歷。 Xzavier.prototype也沒有job屬性
3、找到Xzavier.prototype對象的[[Prototype]],指向其對應的對象Object.prototype。Object.prototype也沒有job屬性
4、尋找Object.prototype的[[Prototype]]屬性,返回undefined。
說了函數的原型鏈,這里需要說一下的變量和內部函數。
私有變量和內部函數私有成員,即定義函數內部的變量或函數,外部無法訪問。
function Xzavier(){ var name = "xzavier"; //私有變量 var sports = function() {console.log("basketball")}; //私有函數 } var x = new Xzavier(); x.name; //undefined
如果要訪問,需要對外提供接口。
function Xzavier(){ var name = "xzavier"; //私有變量 var sports = function() {console.log("basketball")}; //私有函數 return{ name: name, sports: sports } } var x = new Xzavier(); x.name; //"xzavier"靜態變量和內部函數
用點操作符定義的靜態變量和內部函數就是實例不能訪問到的變量和內部函數。只能通過自身去訪問。
function Xzavier(){ Xzavier.name = "xzavier"; //靜態變量 Xzavier.sports = function() {console.log("basketball")}; //靜態函數 } Xzavier.name; //"xzavier" var x = new Xzavier(); x.name; //undefined實例變量和內部函數
通過this定義給實例使用的屬性和方法。
function Xzavier(){ this.name = "xzavier"; //實例變量 this.sports = function() {console.log("basketball");}; //實例函數 } Xzavier.name; //undefined var x = new Xzavier(); x.name; //"xzavier"原型鏈繼承
有了原型鏈,就可以借助原型鏈實現繼承。
function Xzavier() { this.name = "xzavier"; this.sex = "boy"; this.job = "jser"; } function X() {};
X的原型X.prototype原型本身就是一個Object對象。F12打開控制臺輸入函數,再打印X.prototype:
Object { constructor: X() __proto__: Object }
prototype本身是一個Object對象的實例,所以其原型鏈指向的是Object的原型。
X.prototype = Xzavier.prototypeX.prototype = Xzavier.prototype;
這樣相當于把X的prototype指向了Xzavier的prototype;
這樣只是繼承了Xzavier的prototype方法,Xzavier中的自定義方法則不繼承。
X.prototype.love = "dog";
這樣也會改變Xzavier的prototype,所以這樣基礎就不好。
X.prototype = new Xzavier()X.prototype = new Xzavier();
這樣產生一個Xzavier的實例,同時賦值給X的原型,也即X.prototype相當于對象:
{ name: "xzavier", sex: "boy", job: "jser", [[Prototype]] : Xzavier.prototype }
這樣就把Xzavier的原型通過X.prototype.[[Prototype]]這個對象屬性保存起來,構成了原型的鏈接。
不過,這樣X產生的對象的構造函數發生了改變,因為在X中沒有constructor屬性,只能從原型鏈找到Xzavier.prototype,讀出constructor:Xzavier。
var x = new X; console.log(x.constructor); 輸出: Xzavier() { this.name = "xzavier"; this.sex = "boy"; this.job = "jser"; }
手動改正:
X.prototype.constructor = X;
這是X的原型就多了個屬性constructor,指向X。這樣就OK。
function Xzavier() { this.name = "xzavier"; this.sex = "boy"; this.job = "jser"; } function X(){} X.prototype = new Xzavier(); var x = new X() x.name // "xzavier"[[Prototype]],__proto__,prototype
關于我們經常遇到的[[Prototype]],__proto__,prototype:
我們在控制臺打印 var str = new String("xzavier"),展開查看屬性時,只會看到__proto__,所以起作用的是__proto__,__proto__是對象的內置屬性,是每個對象都有的屬性,但是這個屬性使用不標準,所以不建議直接使用。但是,我們的原型鏈就是基于 __proto__的。通過構造函數得到的實例的 __proto__ 屬性,指向其對應的原型對象 String.prototype,這正如文中我們打印 var str = new String("xzavier") 中看到的一樣。
[[Prototype]]是一個隱藏屬性,指向的是這個對象的原型。幾乎每個對象有一個[[prototype]]屬性。
而prototype是每個函數對象都具有的屬性,指向原型對象,如果原型對象被添加屬性和方法,那么由應的構造函數創建的實例會繼承prototype上的屬性和方法,這也是我們在代碼中經常遇到的。構造函數產生實例時,實例通過其對應原型對象的 constructor 訪問對應的構造函數對象。所以,我們繼承出來的實例往往沒有constructor,只是通過原型鏈查找,會讓我們產生錯覺,可參見本系列原型鏈文章。
hasOwnPropertyhasOwnProperty是Object.prototype的一個方法,判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性。
hasOwnProperty 是JavaScript中唯一一個處理屬性但是不查找原型鏈的函數。
function Xzavier() { this.name = "xzavier"; this.sex = "boy"; this.job = "jser"; } //給A的原型對象添加屬性 Xzavier.prototype.sports = function() {console.log("basketball");}; var x = new Xzavier(); x.name; // "xzavier" "sex" in x; // true x.hasOwnProperty("job"); // true x.hasOwnProperty("sports"); // false
當檢查對象上某個屬性是否存在時,hasOwnProperty 是非常推薦的方法。
繼承在js中使用頻繁。ES6也設計了專門的CLASS語法糖供開發者使用。
更多繼承方法在新的文章中更新...
難得周末,應該運動O(∩_∩)O~ 打打籃球,運動運動,有代碼,有籃球,有生活。。。
長時間不動肩膀(其實身體各地方都是),還真疼啊。希望程序猿們都健健康康的?。?!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90946.html
摘要:該對象包含了函數的所有局部變量命名參數參數集合以及,然后此對象會被推入作用域鏈的前端。如果整個作用域鏈上都無法找到,則返回。此時的作用域鏈包含了兩個對象的活動對象和對象。 前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:閉包 JavaScript-閉包 閉包(closure)是一個讓人又愛又恨的somet...
摘要:對象創建字面量方式構造函數方式也可以這樣不過這樣的話,為何不選擇字面量方式字面量方式和方式的寫法是等價的,返回的結果是同種類的對象。構造函數產生實例時,實例通過其對應原型對象的訪問對應的構造函數對象。 前端學習:教程&模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試資源匯總 歡迎提issues斧正:對象&對象使用 Object對象 在 JavaScript 中,對...
之前也有和大家講過有關JS的對象創建和對象繼承,本篇文章主要為大家做個匯總和梳理。 JS中其實就是原型鏈繼承和構造函數繼承的毛病,還有就是工廠、構造、原型設計模式與JS繼承。 JS高級程序設計4:class繼承的重點,不只是簡簡單單的語法而已。 對象創建 不難發現,每一篇都離不開工廠、構造、原型這3種設計模式中的至少其一! 那JS為什么非要用到這種3種設計模式了呢?? 我們先從對...
摘要:創建數組數組字面量數組構造函數參數為數組建議使用數組字面量方式,性能好,代碼少,簡潔,畢竟代碼少。數組判斷方法用來判斷某個值是否為。的這是最簡潔最直接的遍歷數組元素的語法。把數組轉換為本地數組,并返回結果。 前端學習:前端教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:數組&數組方法使用詳解 Array對象 之前一...
閱讀 2249·2021-11-22 09:34
閱讀 2012·2021-09-22 15:22
閱讀 2015·2019-08-29 15:05
閱讀 2105·2019-08-26 10:43
閱讀 3406·2019-08-26 10:26
閱讀 876·2019-08-23 18:29
閱讀 3518·2019-08-23 16:42
閱讀 1994·2019-08-23 14:46