一、理解继承
继承可以理解为实例想要继承原型链上其它对象的属性
二、继承方式总结
方式一:原型继承
- 特点:可以继承到来自原型链上对象的属性,因此对象与对象之间通过__proto__指定或者通过Object.setPrototypeOf来设定,继承到的属性都是一样的, 原型链上的某个对象改变属性的值,所有的对象访问的结果均会改变,这时我们会想到构造函数的好处,可以动态传入
let obj = {
type: 'object',
getType: function() {
return this.type
}
}
let obj1 = {}
obj1.__proto__ = obj
// Object.setPrototypeOf(obj1, obj)
console.log(obj1.type)
console.log(obj1.getType)
打印结果
object
[Function: getType]
- 观察obj1:在浏览器打印obj1,我们可以看到,obj1在原型链上具有type和getType属性,因此obj1.type和obj1.getType可以打印结果
方式二:构造函数继承
- 特点:可以继承构造函数中已经定义好的属性,也可以动态传入属性值进行定义,但是相对于原型继承也有缺点,就是不需要动态传参定义的属性在创建实例的时候也要再分配空间定义一次
function Person(name) {
this.name = name
this.type = 'Function',
this.getType = function() {
return this.name
}
}
let p1 = new Person('p1')
console.log(p1.name, p1.type, p1.getType)
输出结果
p1 Function [Function]
- 观察p1,p1具有三个属性,同理创建p2 p3同样是三个新的属性,这和原型继承对比起来就有点浪费空间
方式三:原型和构造函数组合式继承
- 特点:需要动态传参的属性写到构造函数中,不需要改变的属性和方法属性均定义到原型prototype上
function Person(name) {
this.name = name
}
Person.prototype.type = 'Function'
Person.prototype.getType = function() {
return this.name
}
let p1 = new Person('p1')
console.log(p1.name, p1.type, p1.getType)
输出
p1 Function [Function]
- 观察一下p1,name属性是新建的,但是type和getType都是继承来的,目前这种方式比较合理
方式四:Class继承(ES6新增)
- 特点:可以自定义属性,方法可实现原型继承
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
this.type = 'class'
}
hello() {
console.log('hello world');
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y);
this.color = color; // 正确
}
}
let p1 = new ColorPoint(1, 2, 'red')
console.log(p1)
打印
ColorPoint { x: 1, y: 2, type: 'class', color: 'red' }
console.log(p1.hello)
打印
Function
- 观察p1,非方法属性都是当前对象新建的,方法属性是继承来的
三、总结
组合继承和class比较常用