参考文章:一文看懂 JS 继承
构造函数继承
优势
-
可以定义私有属性方法
-
子类传递参数给父类
劣势
-
不能定义共享的属性方法
-
共享的属性方法需要写在外面 失去了封装性
:chestnut:
let share = [1, 2, 3];
function log () {
console.log(this.name);
}
function Parent (name, friends) {
this.name = name;
this.friends = friends;
this.share = share;
this.log = log;
}
function Child (name, friends, gender) {
Parent.call(this, name, friends);
this.gender = gender;
}
原型链继承
原型链模式需要手动重新绑定 constructor 而且不能定义私有变量
优势
- 可以定义公有属性和方法
劣势
-
无论是定义还是继承都需要手动修改 constructor
-
封装性一般
-
不能定义私有属性方法
-
没办法向父类传递参数
:chestnut:
function Parent () { };
Parent.prototype = {
constructor: Parent,// 需要手动绑定constructor
name: 'oli',//不能定义私有属性 全部都是公有的
friends: ['alice', 'troy'],// 方法和属性都是公有的 所有实例都引用这个
log: function () {
return this.name
}
}
// 封装性一般
function Child () { };// 没办法向父类传递参数
Child.prototype = new Parent();// 使用new 操作符创建并重写prototype
console.log(Child.prototype.constructor);
Child.prototype.constructor = Child; // 每次继承都需要手动修改constructor
组合继承 原型链继承+构造函数继承
优势
-
公有的写在原型
-
私有的卸载构造函数
-
可以向父类传递参数
劣势
-
需要手动绑定constructor
-
封装性一般
-
重复调用父类性能损耗
:chestnut:
function Parent (name, friends) {
// 私有的部分
this.name = name;
this.friends = friends;
}
Parent.prototype = {
// 公有的写这里
constructor: Parent,// 需要手动绑定
share: [1, 2, 3],
log: function () {
return this.name;
}
}
// 封装性一般
function Child (name, friends, gender) {
Parent.call(this, name, friends); // 这里调用了一次Parent
this.gender = gender;
}
Child.prototype = new Parent(); // 这里又调用了一次Parent
Child.prototype.constructor = Child;//需要手动修改constructor
原型式继承
原型式继承方法直接使用ES5object.create
方法
object.create原理
-
创建一个构造函数,构造函数的原型指向对象,
-
调用 new 操作符创建实例,并返回这个实例,
-
本质是一个浅拷贝
优点
- 父类方法可以复用
缺点
-
父类引用属性全部被共享
-
子类不可传递参数给父类
:chestnut:
let parent = {
name: 'parent',
share: [1, 2, 3],// 父类的属性全部被子类共享
log: function () { // 父类的方法可以复用
return this.name;
}
}
let child = Object.create(parent);
寄生式继承
在原生式继承的基础上为子类增加属性和方法 二次封装
优势
-
父类方法可以复用
-
增加了别的属性和方法
劣势
-
父类引用属性全部被共享
-
子类不可传递参数给父类
:chestnut:
let parent = {
name: 'parent',
share: [1, 2, 3],
log: function () {
return this.name;
}
}
function create (obj) {
let cloneObj = Object.create(obj);
cloneObj.print = function () { // 增加了一些属性和方法
console.log(this.name)
}
return cloneObj;
}
let child = create(parent);
寄生组合式继承
杂糅了原型链式、构造函数式、组合式、原型式、寄生式而形成的一种方式:
主要是解决了组合继承的唯一缺点:多次调用Parent
优点:
-
公有的写在原型
-
私有的写在构造函数
-
可以向父类传递参数
-
不会重复调用父类
缺点
-
需要手动绑定constructor
-
需要调用额外的方法 封装性一般
:chestnut:
function Parent (name, friends) {
this.name = name;
this.friends = friends;
}
Parent.prototype = {
constructor: Parent,//需要手动绑定constructor
share: [1, 2, 3],
log: function () {
return this.name
}
}
function Child (name, friends, gender) {
Parent.call(this, name, friends);
this.gender = gender;
}
function proto(child, parent) {
let clonePrototype = Object.create(parent.prototype)
child.prototype = clonePrototype
child.prototype.constructor = child
}
proto(Child,Parent);
ES6 class
:chestnut:
class Parent {
constructor(name, friends) { // 该属性在构造函数上,不共享
this.name = name
this.friends = friends
}
log() { // 该方法在原型上,共享
return this
}
}
Parent.prototype.share = [1, 2, 3] // 原型上的属性,共享
class Child extends Parent {
constructor(name, friends, gender) {
super(name, friends)
this.gender = gender
}
}
网友评论