js 原型鏈 __proto__ prototype
阿新 • • 發佈:2019-02-10
原型鏈
在建立一個函式時,就自動為該函式新增一個prototype屬性,
該屬性指向原型物件,預設情況下,該物件中只包塊一個constructor屬性,
它是一個指向prototype屬性所在函式的指標。
var Person = function () {};
var p = new Person();
我們來看看這個new究竟做了什麼?我們可以把new的過程拆分成以下三步:
下面來個例子理解下所謂的原型鏈<1> var p = {}; //建立一個空物件p <2> p.__proto__ = Person.prototype; //修改p的__proto__屬性指向,指向Person的prototype <3> Person.call(p); //修改Person物件的this指標,指向物件p
var Person = function(name){
this.name = name;
}
Person.prototype.say = function(){
alert(this.name);
}
var p = new Person('Jack');
p.say();
原型鏈通過__proto__維繫
那麼__proto__是什麼?
每個物件都會在其內部初始化一個屬性,就是__proto__,當我們訪問一個物件的屬性時,如果這個物件內部不存在這個屬性(本地屬性),那麼它就會去__proto__裡找這個屬性。而這個__proto__同樣是一個物件,又會有自己的__proto__,於是就這樣一直構造下去,直到最後一個物件的__proto__屬性為null,就形成了我們平時所說的原型鏈。
查詢順序
每個物件都有一個原型物件,由於原型物件本身也是物件,根據上邊的定義,它也有自己的原型,而它自己的原型物件又可以有自己的原型,這樣就組成了一條鏈,這個就是原型鏈。JavaScritp引擎在訪問物件的屬性時,如果在物件本身中沒有找到,則會去原型鏈中查詢,
tip:
如果原型鏈,本地屬性有相同的方法,那麼會優先在本地查詢並執行,原型鏈上的方法就不執行了。同樣的,屬性的查詢也是這麼個順序。
下面通過兩個小例子說明屬性和方法查詢順序:
1>
function Foo() {
this.say = function(){
alert('本地方法');
}
}
A.prototype.say = function() {
alert('prototype方法');
}
new Foo().say();
很顯然,alert出來的結果肯定是“本地方法”這條資訊,這說明了屬性和方法的查詢是從本地開始的。
2>
var base = {
name : "base",
getInfo : function(){
return this.id + "," + this.name;
}
}
var ext = {
id : 0,
__proto__ : base
}
console.log(ext.getInfo());// 0,base
//
var base = {
name : "base",
getInfo : function(){
return this.id + "," + this.name;
}
}
var ext = {
id : 0,
name : "ext",
__proto__ : base
}
console.log(ext.getInfo());// 0,ext
前者結果為"0, base",ext中沒找到name屬性,就通過__proto__構成的原型鏈找到了base身上,正好base中有該屬性,結果為"base"。
後者結果為"0,ext",那是因為首先在ext中找到了屬性name,結果為"ext"。這裡要注意的是,ext在呼叫base中的getInfo時,this指向的其實是ext物件,而不是base,因此得到的結果才會是"ext"。