原生js深刻理解系列(五)--- 透析原型與原型鏈

概念:函數

JavaScript 常被描述爲一種基於原型的語言 (prototype-based language)——每一個對象擁有一個原型對象,對象以其原型爲模板、從原型繼承方法和屬性。原型對象也可能擁有原型,並從中繼承方法和屬性,一層一層、以此類推。這種關係常被稱爲原型鏈 (prototype chain),它解釋了爲什麼一個對象會擁有定義在其餘對象中的屬性和方法。測試

JavaScript 只有一種結構:對象。每一個實例對象(object )都有一個私有屬性(稱之爲__proto__)指向它的原型對象(prototype)。該原型對象也有一個本身的原型對象(__proto__) ,層層向上直到一個對象的原型對象爲 null。根據定義,null 沒有原型,並做爲這個原型鏈中的最後一個環節。this

準確地說,這些屬性和方法定義在Object的構造器函數(constructor functions)之上的prototype屬性上,而非對象實例自己。spa

在 JavaScript 中並不如此複製——而是在對象實例和它的構造器之間創建一個連接(它是__proto__屬性,是從構造函數的prototype屬性派生的),以後經過上溯原型鏈,在構造器中找到這些屬性和方法。.net

應用:prototype

eg: function Person(name){3d

this.name = namecode

}對象

Person.prototype.props = '43d'blog

var per1 = new Person();

console.log(per1.props);//43d,構造函數上的prototype屬性能夠被實例繼承

console.log(per1.__proto__ === Person.prototype) // true,即實例的__proto__屬性與構造函數的prototype屬性是同一個,也就是說per1的__proto__屬性就是Person.prototype

console.log(Object.getPrototypeOf(per1)===Person.prototype) // true,理解原型和原型鏈

//--- 測試代碼結束

注意: 理解對象的原型(能夠經過Object.getPrototypeOf(obj)或者已被棄用的__proto__屬性得到)與構造函數的prototype屬性之間的區別是很重要的。前者是每一個實例上都有的屬性,後者是構造函數的屬性。也就是說,Object.getPrototypeOf(new Foobar())Foobar.prototype指向着同一個對象

接上面測試代碼新增一個實例對象

var per2 = new Person('trwW');

看看per1實例與per2實例的展開形式及對這個兩個實例的說明以下圖

理解原型對象:

實例的原型對象是構造器中的成員還加上Object的成員(成員:屬性和方法);拿上例說。per1的原型對象是Person構造器的props,name同時也有一些其餘成員—— toString、valueOf 等等——這些成員定義在 Person() 構造器的原型對象、即 Object之上;

eg:

per1.valueOf
ƒ valueOf() { [native code] }

prototype 屬性:繼承成員被定義的地方

因而 Object.prototype.toString()、Object.prototype.valueOf() 等等成員,適用於任何繼承自 Object() 的對象類型,包括使用構造器建立的新的對象實例。

Object.is()Object.keys(),以及其餘不在 prototype 對象內的成員,不會被「對象實例」或「繼承自 Object() 的對象類型」所繼承。這些方法/屬性僅能被 Object() 構造器自身使用。

也就是說掛在prototype屬性下的成員均可以被繼承。其餘都不行

this 關鍵字沒有指向當前對象的原型對象,原型對象是一個內部對象,應當使用__proto__ 訪問

eg:

console.log(per1.__proto__.props) // "43d"

var per3 = new Person('per3');

使用create方法建立新對象,create() 實際作的是從指定原型對象建立一個新的對象,per1是指定的原型對象。建立了新對象per4

var per4 = Object.create(per1);

per4.__proto__===per1 // true

constructor屬性

實例的.constructor屬性返回的結果是這些實例的原始定義。

per1.constructor;

per2.constructor;

per3.constructor;

per4.constructor;

這四個都是能夠打印出下面的結果

Person(name){

this.name = name

}

即都將返回 Person() 構造器,由於該構造器包含這些實例的原始定義。

constructor的妙用能夠用來判斷某個變量的類型

1.      var aa = [1,2];

console.log(aa.constructor===Array) // true,

2.     bb =()=>{}

console.log(bb.constructor===Function) // true,

修改原型。從修改prototype的值那裏能夠改變原型的值

理解了原型與原型鏈,要探究下,繼承的多種方法請移步本人的博客https://my.oschina.net/u/2542841/blog/2878806

相關文章
相關標籤/搜索