一篇文章輕鬆搞懂原型對象和原型鏈

頭疼的原型對象和原型鏈

我想不少剛接觸Javascript的新手對於原型對象(prototype)和原型鏈(__proto__)的區別和含義都表示真尼瑪操蛋,下面就讓我來結合簡單的例子來讓你徹底明白什麼是原型對象,什麼是原型鏈。

prototype和__proto__的區別

不要想那麼多,你先要知道prototype是函數纔有的屬性,__proto__是所有對象都有的屬性。

var person = { name:'test',age:'20'}
console.log(person.prototype)   // 輸出undefined
console.log(person.__proto__)   // 輸出Object {}

function fun(){console.log("fun")}
console.log(fun.prototype)      // 輸出Object {}
console.log(fun.__proto__)      // 輸出function () {}

什麼是原型對象(prototype)?

原型對象的用途是爲每個實例對象存儲共享的方法和屬性。通俗的講,一個對象的原型對象是被繼承自它的對象共享的,如B繼承自A,當訪問B中的屬性時,會先找B自己的實例屬性,找不到就會到A的原型對象裏面去找。注意,B不會去自己的原型對象裏面去找,也不會去A的實例屬性集合中找,讓我們看個例子就明白了:

function Person(){
    this.name = "Person";               
    this.age = 100;                     
}
Person.printName = function(){          //存於Person的實例屬性中
    console.log(this.name);
}
Person.prototype.printAge = function(){ //存於Person的原型對象中
    console.log(this.age);
}
Person.prototype.name = "oPerson";      //存於Person的原型對象中

console.log(Person.name);               //"Person"
console.log(Person.printName);          //printName函數,因爲printName屬於Person的實例屬性
console.log(Person.printAge);           //undefined,說過了對象不會訪問自己的原型對象的

var person = new Person();
person.prototype.age = 50;  // 這樣寫是會報錯的,因爲person不是一個函數,所以沒有原型對象
console.log(person.name);   // "Person",person繼承自Person,自然也繼承了name和age屬性
console.log(person.age);    // "100",person繼承自Person,自然也繼承了name和age屬性

person.printAge();          //100,person中沒有找到就去Person的原型對象裏面找咯
person.printName();         //報錯,person實例屬性中沒有,Person原型對象中也沒有,我能怎麼辦?

什麼是原型鏈(__proto__)?

上面說了,如果B繼承自A,那麼訪問B的屬性時,就會依次查找B的實例屬性和A的原型對象,那麼問題來了?B怎麼知道自己的上一級是誰?肯定要用個變量存起來吧?這個變量就是__proto__,一個對象的__proto__指向上一級的prototype,兩者是完全相等的。Object的__proto__爲null。那麼什麼是原型鏈?我們知道B的__proto__指向A的prototype,A的__proto__指向Object的prototype,Object的__proto__指向null,這樣一串B->A->Object的鏈子就叫原型鏈!

person.__proto__ === Person.prototype   // true,可見兩者是完全相同的
Person.__proto__ === Function.prototype // true,可見Person繼承自Function
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章