前端面試題 - 說一下原型和原型鏈?
JavaScript 中,萬物皆對象,對象分爲普通對象和函數對象。 所有的函數都是函數對象(typeof f === 'function'
),其他都是普通對象(typeof o === 'object'
)。
JS在沒有類class
前,創建一個對象都是通過 new 函數()
來實現的(也就是構造函數),例如:
var a = new Object() // 此時a是{}
var a = {} // 等價於 var a = new Object()
function b() {}
var a = new b() // 此時a是{}
在 JavaScript 中,每當定義一個對象(函數也是對象)時候,對象中都會包含一些預定義的屬性。 其中每個函數對象都有一個prototype 屬性,這個屬性就是所謂的原型對象。 可以把原型對象是函數內維護的一個對象模版,當 new 函數()
,就會把這個對象拷貝一份返回新對象,這樣就完成了對象初始化,例如:
function b() {
b.prototype.c = 1
this.d = '2' // 在構造函數裏,this指向b.prototype
}
var a = new b() // 此時a爲{c: 1, d: '2'}
另外,JS 在創建對象(不論是普通對象還是函數對象)的時候,都有一個叫做__proto__的內置預定義屬性, 用於指向創建它的構造函數的原型對象,例如在上面👆的例子中,a.__proto__ === b.prototype
。
每個對象都有__proto__屬性,但只有函數對象纔有 prototype 屬性。
每個對象都有constructor(構造函數)屬性,這個屬性指向 prototype 屬性所在的函數, 例如在上面👆的例子中,a.constructor === b.prototype.constructor === b
。
注意
Function.prototype
是函數對象,但沒有prototype屬性,即Function.prototype.prototype === undefined
,算是一個偏門知識點吧。
原型鏈:在多重繼承中,一個對象可以是原型的拷貝,同時也是另一個對象的原型。 因此,當你嘗試訪問對象上的屬性時,JavaScript引擎開始從對象自身中查找該屬性, 如果沒有,它會繼續檢查__proto__,一直到沒有__proto__或者找到該屬性。 如果找到最後,此屬性不存在時,返回undefined。
原型鏈的最上層是
Object.prototype
通俗易懂的前端面試題網站: https://www.front-interview.com