摘要:常用继承方式主要分为种原型链继承构造函数继承组合继承原型式继承寄生式继承寄生组合继承以及继承多个对象。所以说,构造函数基础只能继承父类的实例属性和方法,不能继承原型链上的属性和方法。
JavaScript常用继承方式主要分为(7种):原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合继承以及继承多个对象。
1:原型链继承(核心:将父类的实例作为子类的原型)基本概念:重写原型对象,赋予一个新的对象的实例。基本思想就是让一个原型对象指向另一个父类的实例。
function Super() {
//基本数据类型
this.text = "Hello";
}
Super.prototype.getSuperText = function() {
return this.text;
}
function Sub() {
this.subText = "Word";
}
Sub.prototype = new Super();
const instance = new Sub();
console.log(instance);
特点:非常纯粹的继承关系,实例是子类的实例,也是父类的实例。父类新增原型方法或属性,子类都能访问到。
优点:简单易于操作
缺点:对引用类型数据操作会互相(多个实例之间)影响
function Super() {
//复杂对象,也就是引用类型
this.value = [1, 2, 3, 4];
}
Super.prototype.getSuperValue = function() {
return this.value;
}
function Sub() {
this.subText = "Word";
}
Sub.prototype = new Super();
const instance1 = new Sub();
const instance2 = new Sub();
instance1.value.push(5);
console.log(instance2.value);
// (5) [1, 2, 3, 4, 5]
2:构造函数继承
//定义构造函数
function Super(){
this.value = [1, 2, 3, 4];
}
//新增属性getSuperValue
Super.prototype.getSuperValue = function() {
return this.value;
}
//sub每次执行都要重新调用
function Sub(){
Super.call(this);
}
const instance1 = new Sub();
instance1.value.push(5);
console.log(instance1.value);
// (5) [1, 2, 3, 4, 5]
const instance2 = new Sub();
console.log(instance2.value);
// (4) [1, 2, 3, 4]
构造函数的特点:(对引用数据类型没有影响)上面的代码输出instance1是1,2,3,4,5,instance2是1,2,3,4。这是因为sub每次在执行时都是重新调用了一个super.call(),而且构造函数在构建对象的过程中,每次都是创建了一个新的object,因此每次调用sub都会执行一遍super,每次执行时都会有申请一个新的内存空间,所以得到的两个value值是不一样互不影响的。
缺点:在整个构造函数的基础过程中,上面的代码并没有使用proto和prototype的属性,没有使用的话那么原型链就没有接上。所以说,构造函数基础只能继承父类的实例属性和方法,不能继承原型链上的属性和方法。
3:组合继承通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用。
保留了构造函数继承与原型链继承的优点。但是执行了两次Person,属性重复了。
function Person(name) {
this.name = name;
this.value = ["head", "body", "legs"];
}
Person.prototype.getName = function() {
return this.name;
};
// 构造函数继承
function Teacher(name, school){
// 执行又一次Person
Person.call(this, name);
this.school = school;
}
// 原型链继承
// 执行一次Person
Teacher.prototype = new Person();
const Eric = new Teacher("Eric",27);
Eric.getName();
// 输出:Eric
// prototype构造器指回自己
Teacher.prototype.constructor = Teacher;
Teacher.prototype.getSchool = function() {
return this.school;
};
特点:既可以继承实例属性和方法,也可以继承原型属性和方法。既是子类的实例也是父类的实例,不存在引用属性共享的问题。可以传参,函数可复用。
缺点:调用两次父类构造函数,生成了两份实例。
4:原型式继承借助原型可以基于已有的对象创建新的对象,同时还不必因此创建自定义类型。
原理:(本质)利用一个空对象作为一个中介。
const lakers = {
name: "lakers",
value: ["Micheal", "Wade", "Kobe"]
};
const lakers1 = Object.create(lakers);
const lakers2 = Object.create(lakers);
lakers1.value.push("Fish");
console.log(lakers);
模拟Object.create()
object.create()原理:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了一个可以随意添增属性的实例或对象。
Object.prototype.create = function(obj) {
function Fun() {}
Fun.prototype = obj;
return new Fun();
}
缺点有两点:第一点是无法传递参数,第二点是引用类型存在变量的污染。
5:寄生式继承寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数。
目的:在原型式继承的基础上,寄生增加了一些新的方法和属性。
它的特点同原型式继承一样,也是无法传递参数,而且引用的数据类型也容易存在样式污染。
Object.createNew()
Object.prototype.createNew = function(obj){
var newObj = Object.create(obj);
//获取长度等于一个function
newObj.getLength = function(){ ... };
return newObj;
}
6:寄生组合继承
目的:为了解决数据重复拷贝两遍的问题。
Super只执行一次。
//定义Super构造函数
function Super(name) {
this.name = name;
this.value = ["Hello", "Word"];
}
//在super的原型链添加一个getName
Super.prototype.getName = function() {
return this.name;
};
//定义Sub
function Sub(name, age) {
//调用构造函数继承
Super.call(this, name);
this.age = age;
}
let prototype = Object.create(Super.prototype);
prototype.constructor = Sub;
Sub.prototype = prototype;
Sub.prototype.getAge = function(){
return this.age;
}
const instance1 = new Sub("Eric", 23);
const instance2 = new Sub("Vico", 23);
instance1.value.push("!");
instance2.value.push("!!");
7:继承多个对象
借助原型式继承Object.create拿到SuperClass,也就是父类,拿到父类的prototype之后把它赋给ClassOne,再然后我们将ClassTwo的prototype使用一个Object.assign,一个对象的拷贝,把它拷贝到ClassOne里面来,然后最后ClassOne.prototype.constructor等于ClassOne。
也就是使用一个Class.assign把所有我们想要继承的父类的prototype全部组合到一起完成一个拷贝,之后再赋给对象。
function ClassOne.prototype = Object.create(SuperClass.prototype); Object.assign(ClassOne.prototype, ClassTwo.prototype); ClassOne.prototype.constructor = ClassOne;
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/105852.html
摘要:特点跟借用构造函数模式一样,每次创建对象都会创建一遍方法。缺点寄生组合式继承使用时说明解决了组合继承存在的问题特点只调用了一次构造函数,并且因此避免了在上面创建不必要的多余的属性原型链还能保持不变还能够正常使用和缺点参考资料 原型链继承 //父类 function Person(name, age) { this.name = name; this.age = age; ...
摘要:可以通过构造函数和原型的方式模拟实现类的功能。原型式继承与类式继承类式继承是在子类型构造函数的内部调用超类型的构造函数。寄生式继承这种继承方式是把原型式工厂模式结合起来,目的是为了封装创建的过程。 js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。...
摘要:原型继承与类继承类继承是在子类型构造函数的内部调用父类型的构造函数原型式继承是借助已有的对象创建新的对象,将子类的原型指向父类。 JavaScript 继承方式的概念 js 中实现继承有两种常用方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) JavaScript不是真正的面向对象的语言,想实现继承可以用JS的原型prototype机制或者call和apply方法 在面...
摘要:原型式继承利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。其中表示构造函数,一个类中只能有一个构造函数,有多个会报出错误如果没有显式指定构造方法,则会添加默认的方法,使用例子如下。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导)showImg(https://segmentfault.com/img/rem...
摘要:可以看出,这个查找过程是一个链式的查找,每个对象都有一个到它自身原型对象的链接,这些链接组件的整个链条就是原型链。原型的构建字面量方式当通过字面量方式创建对象时,它的原型就是。 面向对象 JavaScript没有类(class)的概念的(ES6 中的class也只不过是语法糖,并非真正意义上的类),而在JavaScript中,在 JavaScript 中,除了 String, Numb...
阅读 3062·2021-11-22 13:54
阅读 1352·2021-10-14 09:48
阅读 2490·2021-09-08 09:35
阅读 1726·2019-08-30 15:53
阅读 1351·2019-08-30 13:14
阅读 791·2019-08-30 13:09
阅读 2712·2019-08-30 10:57
阅读 3504·2019-08-29 13:18