目錄
原型鍊 & 繼承
Javasctript
和Java不同,它是prootype base
的語言,而非class base
每個物件都有
一個連結到其他物件的
私屬性,而這個私屬性就是prototype
每個物件的prototype又有自己的prototype,這些prototype會一路指到null
去。這
個一路往null指去的就是原型鍊
因為原型鍊,當你嘗試存取物件的某個屬性,不只會找物件本身,也會去找prototype,然後一路找到null去,所以太長的原型鍊、存取一個不存在的屬性會對效能造成衝擊
The lookup time for properties that are high up on the prototype chain can have a negative impact on the performance, and this may be significant in the code where performance is critical. Additionally, trying to access nonexistent properties will always traverse the full prototype chain.
例
不透過prototype的話你可能會這樣幫每個Person建立出來的實例加上方法
function Person(name, skill) {
this.name = name;
this.skill = skill;
}
function Politician(name, skill) {
Person.call(this, name, skill);
}
function saySomethingRidiculous(content){
return `${this.name}: ${content}`;
}
const clock = new Politician('時鐘', '報數');
const bald = new Politician('韓導', '膝蓋走路');
// 重複加上同個function顯然不太好
clock.saySomethingRidiculous = saySomethingRidiculous;
bald.saySomethingRidiculous = saySomethingRidiculous;
clock.saySomethingRidiculous('粗暴言論大可不必');
bald.saySomethingRidiculous('高雄發大財');
可以使用原型鍊的概念,將function加在建構函式的prototype
,這樣就會自動傳給
用該建構函式建立的實例
prototype is the object that is used to build proto when you create an object with new
Every instance created from a constructor function will automatically have the constructor's prototype property as its [[Prototype]]
但需要注意,這也代表如果加saySomethingRidiculous在Person.prototype的話clock和bald是無法使用的
function Person(name, skill) {
this.name = name;
this.skill = skill;
}
function Politician(name, skill) {
Person.call(this, name, skill);
}
Politician.prototype.saySomethingRidiculous = function(content){
return `${this.name}: ${content}`;
}
const clock = new Politician('時鐘', '報數');
const bald = new Politician('韓導', '膝蓋走路');
clock.saySomethingRidiculous('粗暴言論大可不必');
bald.saySomethingRidiculous('高雄發大財');
要確認某個屬性是物件本身擁有,還是來自它的原型,可以使用hasOwnProperty()
// 如果透過clock.saySomethingRidiculous = saySomethingRidiculous;加屬性的話則會是true
Alex.hasOwnProperty('talkingShit'); // false代表來自prototype
Alex.hasOwnProperty('skill'); // true
prototype & __proto__
__proto__
實例的proto(在chrome看到會顯示[[prototype]])來自於建構函式的prototype
The Constructor.prototype property will become the [[Prototype]] of the constructor's instances
雖然目前瀏覽器仍支援這個屬性,但不推薦使用
,因為它可能會從網頁標準被移除、目前只有被納入ES6標準
若可以的話用Object.getPrototypeOf()、Object.setPrototypeOf()代替它
This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes.
The use of proto is controversial and discouraged. It was never originally included in the ECMAScript language spec, but modern browsers implemented it anyway. Only recently was the proto property standardized by the ECMAScript 2015 specification for compatibility with web browsers, so it will be supported into the future. It is deprecated in favor of Object.getPrototypeOf/Reflect.getPrototypeOf and Object.setPrototypeOf/Reflect.setPrototypeOf (though still, setting the [[Prototype]] of an object is a slow operation that should be avoided if performance is a concern).
prototype
兩者的關係
接下來透過建構函式和實例來看一下prototype與proto的關係
function Person(name, skill) {
this.name = name;
this.skill = skill;
}
function Politician(name, skill) {
Person.call(this, name, skill);
}
const clock = new Politician('時鐘', '報數');
已知clock是由Politician new出來的,故Politician是它的constructor
clock.constructor; // ƒ Politician(name, skill) { Person.call(this, name, skill); }
// 故兩者會相等
clock.constructor.prototype === Politician.prototype; // true
再來__proto__會指向實例的constructor的prototype
clock.__proto__ === clock.constructor.prototype; // true
Object.getPrototypeOf(clock) === clock.constructor.prototype; // true
// 故兩者會相等
clock.__proto__ === Politician.prototype; // true
Object.getPrototypeOf(clock) === Politician.prototype; // true
建構函式的prototype.constructor預設會指向建構函式自身
Constructor.prototype by default has one own property: constructor, which references the constructor function itself
Politician.prototype.constructor === Politician;
參考資料
MDN - Object.prototype.proto
MDN - Inheritance and the prototype chain
函式 - 原型的起手式
js中proto和prototype的區別和關係
Javascripter 必須知道的繼承 prototype, [[prototype]], proto
proto VS. prototype in JavaScript