function parent (age) { this.age = age } parent.prototype.say = function () { console.log(this.age) } function sub (age, value) { parent.call(this, age) this.value = value } sub.prototype = Object.create(parent.prototype, { constructor: { value: sub, enumerable: false, writable: true, configurable: true } })
關於Class的語法推薦看這裏:es6.ruanyifeng.com/#docs/class前端
ES6 的class能夠看做只是一個語法糖,它的絕大部分功能,ES5 均可以作到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。可是它們仍是有區別的。es6
區別:express
能夠繼承原生構造函數編程
根據上面的區別,咱們一步步的看。函數
解決問題:post
function _checkType (obj, constructor) { if (!(obj instanceof constructor)) { throw new TypeError('Cannot call a class as a function') } }
解決問題:this
// 修改構造函數描述符 function defineProperties (target, descriptors) { for (let descriptor of descriptors) { descriptor.enumerable = descriptor.enumerable || false descriptor.configurable = true if ('value' in descriptor) { descriptor.writable = true } Object.defineProperty(target, descriptor.key, descriptor) } } // 構造class // constructor 表示類對應的constructor對象 // protoDesc 表示class內部定義的方法 // staticDesc 表示class內部定義的靜態方法 function _createClass (constructor, protoDesc, staticDesc) { protoDesc && defineProperties(constructor.prototype, protoDesc) staticDesc && defineProperties(constructor, staticDesc) return constructor }
const Foo = function () { function Foo(name) { _checkType(this, Foo) // 先檢查是否是new調用的 this.name = name } _createClass (Foo, [ // 表示在class內部定義的方法 { key: 'say', value: function () { console.log(this.name) } } ], [ // 表示在class內部定義的靜態方法 { key: 'say', value: function () { console.log('static say') console.log(this.name) } } ]) return Foo }()
到這裏class實現完成,驗證一下。spa
const foo = new Foo('aaa')
可見say方法是不可枚舉的。prototype
可見靜態方法say是不可枚舉的。3d
解決問題:
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not' + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }) if (superClass) { Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass } }
解決的問題:
能夠繼承原生構造函數
// 返回父類的this;若爲null,則返回自身 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === 'object' || typeof call === 'function') ? call : self }
const Child = function (_Parent) { _inherits(Child, _Parent) // 繼承父類原型上的屬性及靜態方法的繼承 function Child(name, age) { _checkType(this, Child) // 先使用父類實例對象this,再返回 const _this = _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this, name)) _this.age = age return _this } return Child }(Foo)
子類class實現完成。驗證一下。
Child並無在自身定義靜態方法,可是它的父類有定義。繼承成功。
const Child = function (_Parent) { _inherits(Child, _Parent) function Child(name, age) { _checkType(this, Child) const _this = _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this, name)) _this.age = age return _this } return Child }(Array) const c = new Child('bbb', 12)
繼承成功。
原文: https://juejin.im/post/684490...
最後,歡迎關注個人公衆號:前端開發博客,每日分享新鮮技術文章。