概念:函數
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] }
因而 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