Js常用的继承方式

更新日期: 2019-07-22 阅读: 2.9k 标签: 继承

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://fly63.com/article/detial/4307

相关推荐

css无继承性的属性有哪些?

继承是一种规则,它允许样式不仅应用于某个特定html标签元素,而且应用于其后代。CSS继承是指设置上级(父级)的CSS样式,上级(父级)及以下的子级(下级)都具有此属性。但并不是所有的属性都可以继承

Js继承背后的场景-prototype,__proto__, [[prototype]]

prototype是构造函数的一个属性,它决定了在构造出来的对象上__proto__属性将是什么样的。如上图所示,理解JavaScript中的继承的关键是要理解母鸡如何产蛋的过程。

js原型继承、构造函数继承、组合继承法

原型继承缺点:1、不能由子对象像父对象传递参数,2、对于引用型的属性修改之后会印象其他的实例对象;构造函数继承缺点:1、不能继承父对象原型上的方法 2、每次实例化对象会重新构建函数,浪费内存。

CSS inherit是继承,那initial和unset呢?

所有CSS都支持几个全局属性值,分别是: inherit , initial 和 unset 。其中 inherit 是继承的意思,IE8(标准版)开始支持,不是从IE9开始支持的,网上一些文档是错误的。

纯手写实现js继承

继承在前端逻辑操作中是比较常见的,今天我们就从零开始写一个js的继承方式,在es5中继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上Parent.call(this)

css的继承性

在面向对象语言都会存在继承的概念,在面向对象语言中,继承的特点:继承了父类的属性和方法。那么我们现在主要研究css,css就是在设置属性的。不会牵扯到方法的层面。

JS之继承(ES5 & ES6)

继承到底是什么?继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法

ES5 的构造函数原型链继承

构造函数,就是专门用来生成实例对象的函数。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。为了与普通函数区别,构造函数名字的第一个字母通常大写。

Js继承总结

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。如果让原型对象指向另一个类型的实例.....有趣的事情便发生了.

JS中8种实现继承的方式

可以使得子类别具有父类别的各种属性和方法,而不需要编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。同时也能添加新的属性和方法。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!