「翻譯」在JavaScript類中可繼承的Static屬性

原文來自 Static Properties in JavaScript Classes with Inheritance(http://thecodebarbarian.com/static-properties-in-javascript-with-inheritance.html)

從ES6開始,JavaScript支持類和類似於其他面向對象編程語言中的static函數。 遺憾的是,JavaScript缺乏對static屬性的支持,而Google搜索出來的解決方案無法考慮繼承。 我在實現一個需要更強大的static屬性概念的Mongoose新功能時遇到了這個問題。 具體來說,我需要通過設置prototype或extends來支持繼承的靜態屬性。 在本文中,我將描述在ES6中實現static屬性的模式。

Static方法和繼承

假設你有一個簡單的帶static方法的ES6類:

「翻譯」在JavaScript類中可繼承的Static屬性

你能使用extends去創建一個子類,同時仍然可以訪問foo()函數:

「翻譯」在JavaScript類中可繼承的Static屬性

你能使用static的getter和setter來設置在Base類中的static屬性:

「翻譯」在JavaScript類中可繼承的Static屬性

遺憾的是,當你有繼承了Base的子類時,此操作會有不良的後果。 如果在一個子類上設置foo,它將為Base類和所有其他子類設置foo。

「翻譯」在JavaScript類中可繼承的Static屬性

如果你的屬性是數組或對象,情況會變得更糟。 由於原型繼承,如果foo是一個數組,每個子類都將會有一個引用指向相同的數組副本,如下所示。

「翻譯」在JavaScript類中可繼承的Static屬性

所以JavaScript支持靜態getter和setter,但是將它們與對象或數組一起使用會是個悲劇。 事實證明,你可以通過JavaScript內置的hasOwnProperty()函數提供一些幫助。

可繼承的Static屬性

關鍵點是,由於JavaScript中的類也是一個對象,所以你能區分它的自有屬性和繼承屬性。

「翻譯」在JavaScript類中可繼承的Static屬性

這種模式適用於類,但它也適用於ES6之前的JavaScript繼承。 這很重要,因為Mongoose仍然使用ES6之前的繼承方式。 事後我們知道應該儘早切換,但這個特性是我們第一次看到的去使用ES6類並且繼承不僅僅是設置函數的prototype的明顯優勢。

「翻譯」在JavaScript類中可繼承的Static屬性

與老式的Sub.prototype = Object.create(Base.prototype)相比,ES6的類具有一個主要優勢,因為extends把靜態屬性和函數都複製了過來。通過使用Object.hasOwnProperty()進行一點額外的工作,你可以創建正確處理繼承的靜態getter和setter。 在JavaScript中使用static屬性要非常小心:因為在底層,extends仍然使用原型繼承。 這意味著static對象和數組在所有子類之間是共享的,除非你使用本文中的hasOwnProperty()模式。


分享到:


相關文章: