關於JS原型、原型鏈、繼承的問題
任何對象都是被構造出來的,構造對象的方法稱為構造函數,構造函數生成的對象為構造函數的實例。聲明一個對象可以var obj = {},也可以var obj = new Object(),前者只是語法糖,等同於new Object。我們稱Object是一個構造函數,任何對象都是由Object所構造出來的。
一、原型
我們也可以自己定義構造函數並且書寫構造函數的原型(prototype)
例如:
function Person(name){
this.name = name;
}
Person.prototype = { //註意:定義構造函數的原型,且要寫在實例化之前
say:function() {
console.log(this.name)
}
}
二、繼承
如上,我們已經定義好了構造函數,書寫好了構造函數的原型,下面進行實例化:
var p1 = new Person("james"); //p1 = { name:"james"}
p1.say(); //"james"
我們發現,p1 對象上並沒有say()方法,但卻可以調用,這是因為p1繼承了其構造函數的原型上的方法。如何繼承的呢?
每個實例化對象上面都有一條隱式的__proto__屬性,它指向著構造函數的原型:
p1.__proto__ === Person.prototype,我們稱p1是由Person所構造出來的
當調用p1.say()方法時,p1對象沒有say這個條屬性,它會去自己的__proto__上面查找,找到後就能調用了
三、原型鏈
每個對象都有自己的原型__proto__,用於繼承構造函數prototype上面的屬性和方法,前面已經說過,prototype也是一個對象,那麽它也有自己的__proto__也可以繼承屬性和方法,一層一層,最終都會指向Object這個關系就叫原型鏈:
p1.__proto__ === Person.prototype //true
Person.prototype.__proto__ === Object.prototype //true
Object.prototype.__proto__ === null //true
另外:
所有的函數(構造函數)也是被構造出來的,由Function所構造。
Function由頂層語言設計出來的,Object也是構造函數,所以也是由Function構造。
Object.__proto__ === Function.prototype //true
Object不是函數嗎?哪來的__proto__?納尼?你在逗我?
函數也是對象,是對象就存在__proto__,所以我只能這麽理解了。
整理一下:
Fucntion 天上來
Function.__proto__ === Function.prototype //我生了我自己
Object.__proto__ === Function.prototype //Function 生出了Object,構造Object同時就定義了Object.protoype
Function.prototype.__proto__ === Object.prototype //註意:這裏的Function.prototype是函數,這是怎麽回事呢?為了保證統一修改了指向,強行指向了Object.prototype
關於JS原型、原型鏈、繼承的問題