在将 ES6 中的 Class 继承时我们会用到Object.create()
方法。所以作为铺垫我们先把这个Object
方法了解一番
从一个栗子开始
讲解之前我们先看一段 ES6 实现继承的代码
1 | class Point { |
通过babel
将其转为 ES5
1 | ; |
这个有点复杂,所以咱们试着将代码简化,去掉验证信息,_createClass
用prototype
代替
1 | ; |
可见 ES6 中的类继承具备以下几个特点:
- 处于严格模式下,给各种属性变量多一层保障(防止变量提升)
- 子类通过原型链继承继承父类的方法,通过构造函数式继承继承父类的属性(防止子类实例间相互污染)
Object.create
也许这个时候Object.create
会问:
别急,咱们慢慢儿来
你刚才肯定没仔细看上边的代码。咱们单拎出来,是不是有一句subClass.prototype = Object.create(superClass.prototype, {...})
1 | function _inherits(subClass, superClass) { |
这东西是用来实现对父类原型对象的继承的。
瞅瞅,通过Object.create()
B继承了A的所有属性和方法
所以这东西可以用下面的代码代替
1 | Object.create = function (obj) { |
不信我给你演示一下
1 | Object.prototype.inher = function(obj){ |
是不是跟上边的一模一样?
不错,Object.create()
的实质正是原型式继承。(中间定义了一个干净的过度类,相当于对类式继承的一种封装)
这东西的属性更改不会造成父属性的变化,还蛮好用的
1 | Object.prototype.inher = function(obj){ |
A、B、C打印结果如下
看到了没,我们更改B
的a
属性时A
的a
属性并未跟着改变。
所以Object.create() 完成的继承在进行属性修改时不会造成父属性的变化。
继承
所以,如果我们希望继承某个类/对象则可以直接使用Object.create(class/obj)
的方法。
如此我们即可动态继承原型的所有属性和方法。
当然,如果我们想要生成一个不继承任何属性(比如没有toString
和valueOf
方法)的对象,可以将Object.create
的参数设为null
。
1 | var obj = Object.create(null); |
继承的实际是原型
1 | var obj1 = { p: 1 }; |
这一点咱们也可以验证一下
所以他本质上和原型链继承一样,修改原型对象C
会影响到原型对象D
。(因为是原型链继承所以B
修改后并未开辟新的存储空间,只是动态的更新了属性a
的值)
第二个参数?
没错。这东西好用就在这里。我们可以通过此方法的第二个参数手动设置子类的对象属性。
1 | var obj = Object.create({}, { |
如此一来我们就可以DIY
子类啦。
我们今后的继承(原型继承)我们就可以通过它来实现。同时下一章的Class
语法我们也会用到这个方法。
那么,后会有期