You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ES5 的继承使用借助构造函数实现,实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面。ES6 的继承机制完全不同,实质是先创造父类的实例对象 this(所以必须先调用 super 方法),然后再用子类的构造函数修改 this。
子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类自己的 this 对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用 super 方法,子类就得不到 this 对象。
ES6 extends 继承做了什么操作
看这个例子:
// ES6classParent{constructor(name){this.name=name;}staticsayHello(){console.log('hello');}sayName(){console.log('my name is '+this.name);returnthis.name;}}classChildextendsParent{constructor(name,age){super(name);this.age=age;}sayAge(){console.log('my age is '+this.age);returnthis.age;}}letparent=newParent('Parent');letchild=newChild('Child',18);
子类构造函数(Child)继承了父类构造函数(Preant)的里的属性。使用 super 调用的(ES5 则用 call 或者 apply 调用传参)。也就是图中用不同颜色标记的两条线。
把上面的例子转化为 ES5(也即是寄生组合式继承的方法):
functionParent(){this.name=name;}Parent.sayHello=function(){console.log("hello");}Parent.prototype.sayName=function(){console.log("my name is "+this.name);returnthis.name;}functionChild(name,age){// 相当于superParent.call(this,name);this.age=age;}function_inherits(Child,Parent){// Object.createChild.prototype=Object.create(Parent.prototype);// __proto__// Child.prototype.__proto__ = Parent.prototype;Child.prototype.constructor=Child;// ES6// Object.setPrototypeOf(Child, Parent);// __proto__Child.__proto__=Parent;}_inherits(Child,Parent);Child.prototype.sayAge=function(){console.log("my age is "+this.age);returnthis.age;}letparent=newParent("Parent");letchild=newChild("Child",18);
类(构造函数)
构造函数创建实例对象的过程和工厂模式类似
构造函数的创建过程:
new
出来的实例对象,因此 this 指向实例对象)原型链继承
基本思路:
利用原型让一个引用类型继承另一个引用类型的属性和方法。即重写原型对象,代之以一个新类型的实例。
构造函数继承
基本思路:
在子类型的构造函数中调用超类型构造函数。
组合继承(原型链+构造函数)
组合继承指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式。
基本思路:
使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,既通过在原型上定义方法来实现了函数复用,又保证了每个实例都有自己的属性。
原型式继承
基本思想:
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
在
objectCreate()
函数内部,先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回了这个临时类型的一个新实例,从本质上讲,objectCreate()
对传入的对象执行了一次浅拷贝。ECMAScript5 通过新增
Object.create(proto[, propertiesObject])
方法规范了原型式继承。这个方法接收两个参数:proto
:新创建对象的原型对象propertiesObject
:可选,新对象定义额外属性的对象(可以覆盖原型对象上的同名属性)在传入一个参数的情况下,
Object.create()
和objectCreate()
方法的行为相同。寄生式继承
寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。
基于
person
返回了一个新对象 -——person2
,新对象不仅具有person
的所有属性和方法,而且还有自己的sayHi()
方法。在考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。寄生组合式继承
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法,基本思路:
不必为了指定子类型的原型而调用超类型的构造函数,我们需要的仅是超类型原型的一个副本,本质上就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下所示:
constructor
属性至此,我们就可以通过调用
inheritPrototype
来替换为子类型原型赋值的语句:寄生组合继承是引用类型最理性的继承范式。
class继承(es6)
ES6 中的类只是 ES5 封装后的语法糖而已。
在 ES5 中类的原型对象的方法是可枚举的,但是 ES6 中不可枚举:
在 ES5 中如果不用
new
,this
指向window
全局变量,在 ES6 如果不用new
关键字则会报错处理:ES6 中的类是不会声明提升的,ES5 可以:
在 ES6 中如果不写构造方法:
在 ES6 中类的属性名可以采用表达式:
ES6
extends
继承做了什么操作看这个例子:
用原型图表示:
结合代码和图可以知道。
ES6
extends
继承,主要就是:Child
)的原型(__proto__
)指向了父类构造函数(Parent)
child
)的原型对象(Child.prototype
) 的原型(__proto__
)指向了父类(parent
)的原型对象(Parent.prototype
)。Child
)继承了父类构造函数(Preant
)的里的属性。使用super
调用的(ES5 则用call
或者apply
调用传参)。也就是图中用不同颜色标记的两条线。把上面的例子转化为 ES5(也即是寄生组合式继承的方法):
参考资料
The text was updated successfully, but these errors were encountered: