原型繼承問題迷失
阿新 • • 發佈:2018-02-08
enume 它的 判斷 lean 經驗 明顯 開發 tor new 的原型鏈(proto)上是否存在
問題描述
在開發中需要實現一個自定義Error,它繼承自Error
,按照經驗,一般會這樣來做:
function CustomError(message) { this.message = message; } CustomError.prototype = Object.create(Error.prototype, { name: { value: ‘customError‘ }, constructor: { value: Error, enumerable: false, writable: true, configurable: true } }); var myError = new CustomError(‘f**k error!‘); console.log(myError instanceof CustomError) // true console.log(myError instanceof Error) // true
它工作的很好,沒有明顯的bug,所以長期以來,我都這麽幹。直到某天試著這樣:
> console.log(CustomError instanceof Error)
< false
為什麽這裏返回的是false
?認真思考,等下給出答案。
再一個,回到題目本身,我想和大家討論的是函數之間的繼承關系。具體而言,就是CustomError
通過原型鏈繼承於Error
,實現預期不僅表現在CustomError
的每一個實例上,也表現在其本身——CustomError instanceof Error === true
解決之道
要解答上面的問題,必須清楚這裏的instanceof
操作,就是判斷CustomError
Error.prototype
,返回一個Boolean。
所以結果false
並不令人感到奇怪,因為沒有任何跡象表明CustomError.__proto__
指向Error.prototype
。
上面這句話暗含了解決之道:
> CustomError.__proto__ = Error.prototype
> CustomError instanceof Error
< true
延展
- 原型(prototype)
每個函數有一個prototype屬性,它的值是一個對象(屬性的集合),默認只有一個constructor屬性。 - 原型鏈(proto)
1、每個對象
2、函數也是對象,也默認有一個__proto__屬性,指向Function.prototype。
3、訪問一個對象的屬性時,先在該對象的基本屬性中查找,如果沒有,在沿著__proto__這條鏈向上查找,這就是原型鏈。 - instanceof 運算符
用來測試一個對象在其原型鏈中是否存在一個構造函數的 prototype 屬性。 - Object.create()
使用指定的原型對象及其屬性去創建一個新的對象(依然維持著對原型對象的引用)。
原型繼承問題迷失