最近在复习JS,此系列文章仅作为笔记,如有错误欢迎评论交流
1.原型链继承
function Parent() {
this.name ='kevin'
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child() {
}
Child.prototype = new Parent()
const child = new Child()
child.name = 'felix'
child.getName() // felix
缺点
- 函数不能传参
- 引用类型的属性会被所有实例【共享】
2.构造函数继承(经典继承)
function Parent(name) {
this.name =name
}
function Child(name) {
Parent.call(this,name)
}
const child1 = new Child('felix')
const child2 = new Child('tom')
console.log(child1.name); // felix
console.log(child2.name); // tom
优点
- 可以传参
- 避免了引用类型的属性被共享 缺点
- 如果构造函数有方法,那么每次创建实例都会被创建一次
3.组合继承
原型链继承和构造函数 1 + 1
function Parent(name) {
this.name =name
}
function Child(name) {
Parent.call(this,name)
}
Child.prototype = new Parent()
Child.prototype.constructor = Child
const child1 = new Child('felix')
const child2 = new Child('tom')
console.log(child1.name); // felix
console.log(child2.name); // tom
融合原型链继承和构造函数继承的优点,是javascript中最常用的继承方式
4.原型式继承
function createObj(o) {
function F(){}
F.prototype = o;
return new F();
}
var person = {
name: 'felix',
friends: ['tom',]
}
var person1 = createObj(person);
var person2 = createObj(person);
person1.name = 'person1';
console.log(person2.name); // felix
person1.friends.push('taylor');
console.log(person2.friends); // ["tom", "taylor"]
修改 person1.name 的值,person2.name 的值并未发生改变,并不是因为 person1 和 person2 有独立的 name 值,而是因为 person1.name = 'person1' ,给 person1 添加了 name 值,并非修改了原型上的 name 值。
5.寄生式继承
function createObj(fn) {
const clone = Object.create(fn)
clone.sayName = function () {
console.log('hi');
}
return clone
}
缺点
- 每次创建对象都会创建一遍方法
6.寄生组合式继承
先来看一下我们之前写的组合继承
function Parent(name) {
this.name = name
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child(name) {
Parent.call(this,name)
}
Child.prototype = new Parent()
const child1 = new Child('felix')
child1.getName()
组合继承最大的缺点是会调用两次父构造函数。
一次是在设置子类型实例原型的时候 Child.prototype = new Parent()
二是在创建子类实例的时候 Parent.call(this,name)
在这里我们打印 child1 和 Child 会发现,Child.prototype 和 child1 中都有 colors 属性,值为['red', 'blue', 'green']
那么如何避免重复调用呢?
其实只要有一个中间函数作为跳板就可以,下面看代码。
function Parent(name) {
this.name = name
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.getName = function () {
console.log(this.name);
}
function Child(name) {
Parent.call(this,name)
}
const F = function () {}
F.prototype = Parent.prototype
Child.prototype = new F()
const child1 = new Child('felix')
child1.getName()
最后我们可以封装一下这个方法
function object(prototype) {
function F() { }
F.prototype = prototype
return new F()
}
function prototype(child,parent) {
const prototype = object(parent.prototype)
prototype.constructor = child
child.prototype = prototype
}
使用