javascript做爲一門輕量級的腳本語言在ES6和node.js的橫空出世以後將其推向的新的高度,雖然 ES6 中出現的新的生成對象的類語法格式,但依然爲ES5的語法糖,而咱們依然有必要從javascript的原生實現入手來了解它的繼承實現方式,ES6給出了更加簡潔的固定的類聲明方式,有興趣的能夠查看阮一峯的ES6入門,下面給出原文連接es6 阮一峯http://es6.ruanyifeng.comjavascript
javascript的繼承不一樣的開發者有不一樣的理解方式,筆者認爲主要分爲四種
- 原型鏈繼承 - 對象冒充繼承(構造函數繼承 不過我不喜歡這個名字) - 組合繼承 - 寄生組合繼承
對於繼承,能夠預先聲明一個Animal, 進而討論不一樣的繼承方式.
let Animal = (function () { function Animal (name) { this.name = name || 'Animal'; this.sleep = function(){ console.log(this.name + '正在睡覺!'); } } Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); } return Animal; })()
原型鏈繼承java
let Cat = (function () { function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; return Cat; })()
原型鏈是 javascript 的典型繼承方式, 這種繼承方式的最大特色就是共享,全部事例共享原型對象中的全部屬性和方法, 共享是它的最大優勢 也是它的最大缺點, 正對咱們的不一樣需求, 好比大多數狀況下咱們經常須要某些屬性是子類特有的 而一些讀取屬性方法須要共享,--另外此種繼承沒法向父類傳參,沒法實現多繼承
對象冒充繼承node
let Cat = (function () { function Cat(name){ Animal.call(this,name); } return Cat; })()
對象冒充繼承就是簡單的利用call或者apply方法實現繼承,這種繼承最大的特色正好與原型鏈繼承相反不能繼承原型屬性/方法--非共享(子類自有一份), 一樣這是它的優勢也是它的缺點, 另外它解決了原型鏈繼承中沒法向父類傳參的缺點, 而且能夠實現某種意義上的多繼承--(注意這種多繼承是打引號的)
組合繼承es6
let Cat = (function () { function Cat(name){ Animal.call(this, name); } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; return Cat; })()
組合繼承是比較好的繼承, 他是原型鏈繼承和對象冒充繼承的合體, 合理的利用了這兩種組合的特色(是特色不是優勢^_^),既是子類的實例,也是父類的實例, 但有一個缺點就是調用了兩次父類構造函數,生成了兩份實例(子類實例將子類原型上的那份屏蔽了)形成內存浪費. 這也是用的最多的一種
寄生組合繼承app
let Cat = (function () { function Cat(name){ Animal.call(this, name); } (function(sub, sup){ var Super = function(){}; Super.prototype = sup.prototype; sub.prototype = new Super(); sub.prototype.constructor = sub })(Cat, Animal) return Cat; })()
寄生組合繼承是對組合繼承的基礎上的昇華, 我的認爲是堪稱完美的繼承方式,改進的組合繼承內存浪費的問題^_^