资讯专栏INFORMATION COLUMN

js各种方法继承以及优缺点

Cristalven / 431人阅读

摘要:的属性是指向的,继承的属性在寄生式继承创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。缺点跟构造函数模式一样,每次创建对象都会创建一遍方法。

前言

上文讲到js中的原型链,这篇文章对每种继承方式具体分析一下

原型链继承

原型链继承就是将父类的实例赋给子类的原型对象,话不多说,看下代码

function parent(name){
    this.name = "111";
}
parent.prototype.getName = function(){
    console.log(this.name)
}
function child(){}
child.prototype = new parent();
const child1 = new child()
child1.getName();//111
console.log(child.name);//111

优点: 可以直接继承父类的属性和方法,这里的属性继承是通过__proto__找到的,不是实例本身拥有的
缺点: 1.不能向父类传参 2.引用属性会被所有实例共享

function parent(){
    this.name = ["111","2222"]
}
parent.prototype.getName = function(){
    console.log(this.name)
}
function child(){}
child.prototype = new parent();
const child1 = new child();
const child2 = new child();
child1.name.push("aaa")
console.log(child1.name,child2.name)//["111","2222","aaa"]

3.child的constructor指向parent,应该予以修复

child.prototype.constructor = child;
构造函数继承

构造函数继承就是在子类调用父类,看代码

function parent(name){
    this.name = name;
}
function child(name){
   parent.call(this,name);
}
const child1 = new child("child");
console.log(child1.name)//child

优点:可以继承父类的属性(这里的属性继承是实例本身自己的),可以向父类传参,引用类型不会被所有实例共享,constructor还是指向自己child
缺点:不能继承父类原型上的方法,方法都在构造函数中定义,每次创建实例都会创建一遍方法。

function parent(name){
    this.name = name;
    this.arr = ["111"]
}
function child(name){
   parent.call(this,name);
}
const child1 = new child("child1");
const child2 = new child("child2")
child1.arr.push("222");
console.log(child1.arr,child2.arr)//(2) ["111", "222"] ["111"]
组合继承

如果结合原型继承和构造函数继承,这样就可以结合其优点,摒弃其缺点了,这就是组合继承

function parent(name){
   this.name = name;
   this.arr = ["111"]
}
parent.prototype.getName = function(){
   console.log(this.name)
}
function child(name){
    parent.call(this,name)
}
child.prototype = new parent();
const child1 = new child("child1");
const child2 = new child("child2");
child1.arr.push("222");
child1.getName();//child1
console.log(child1.arr,child2.arr)//2) ["111", "222"] ["111"]

优点: 可以向父类传参,可以继承父类的属性(子类会有从父类继承的属性,__proto__上基本属性是undefined,引用属性是有的,看下图)和原型上的方法,引用属性不会被共享

缺点: 一个实例会实例化父类两次,parent.call(this,name)调用一次,child.prototype = new parent()调用一次,constructor指向了parent

原型继承
function create(o){
   function F(){};
   F.prototype = o;
   return new F();
}

原型继承其实就是es5的object.create()的实现
看下这段代码

const person = {
   name: "name",
   arr: ["111","222"]
}
const p1 = create(person);
const p2 = create(person);
p1.name = "p1";
p1.arr.push("aaa");
console.log(p1.name,p2.name);//p1,name
console.log(p1.arr,p2.arr);//(3) ["111", "222", "aaa"] (3) ["111", "222", "aaa"]

缺点:会共享引用属性
注意:修改p1.name的值,p2.name的值并未发生改变,并不是因为p1和p2有独立的 name 值,而是因为p1.name = "p1",给person1添加了 name 值,并非修改了原型上的 name 值。p1,p2的constructor属性是指向object的,继承的属性在__proto__

寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。

function createObj (o) {
  var clone = object.create(o);
  clone.sayName = function () {
    console.log("hi");
  }
  return clone;
}

缺点:跟构造函数模式一样,每次创建对象都会创建一遍方法。

寄生组合式继承

终极继承!!寄生组合式继承,结合了以上的优点,来看下代码
组合继承的缺点就是会调用两次父类,如何避免调用两次呢?能不能直接让子类的prototype访问到父类的prototype?当然可以!!看下面的代码

function parent(name){
   this.name = name;
   this.arr = ["111"]
}
parent.prototype.getName = function(){
   console.log(this.name)
}
function child(name){
    parent.call(this,name)
}
//注意!!关键!!
function F(){}
F.prototype = parent.prototype;
child.prototype = new F();

const c1 = new child("c1");
const c2 = new child("c2");
c1.arr.push("ccc");
c1.name = "name";
c1.getName();//name
c2.getName();//c2
console.log(c1,c2);//child {name: "name", arr: Array(2)} child {name: "c2", arr: Array(1)}

优点:可以继承父类的属性和原型上的方法,实例间不会共享引用属性,基本属性也可以继承变成自己的属性,不会执行两遍父类

缺点: 子类的constructor指向指向了父类,应该修复之,可以改写如下
可以改写写上面的关键步骤

function create(o){
   function F(){}
   F.prototype = o;
   return new F();
}
function prototype(child,parent){
   const p = create(parent.prototype);
   p.constructor = child;
   child.prototype = p;
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108306.html

相关文章

  • 深入理解JavaScript

    摘要:深入之继承的多种方式和优缺点深入系列第十五篇,讲解各种继承方式和优缺点。对于解释型语言例如来说,通过词法分析语法分析语法树,就可以开始解释执行了。 JavaScript深入之继承的多种方式和优缺点 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎,再让我...

    myeveryheart 评论0 收藏0
  • js继承从入门到理解

    摘要:问题修改实例的,即修改了构造函数的原型对象的共享属性到此处,涉及到的内容大家可以再回头捋一遍,理解了就会觉得醍醐灌顶。 开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什么,prototype是什么,以及各种继承方法的优点和缺点,想必有好...

    不知名网友 评论0 收藏0
  • javascript 中各种继承方式的缺点

    摘要:中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现。下面对各种实现方式进行分析,总结各自的优缺点。一原型继承通过改变原型对象实现继承保持构造函数和原型对象的完整性说明是继承而来的属性复用了方法优点父类的方法得到了复用。 javascript中实现继承的方式有很多种,一般都是通过原型链和构造函数来实现。下面对各种实现方式进行分析,总结各自的优缺点。 一 原型继承 let Sup...

    desdik 评论0 收藏0
  • js中对数据类型的总结及判断数据类型的各种方法缺点

    摘要:最常见的判断方法它的官方解释操作符返回一个字符串,表示未经计算的操作数的类型。另外,是判断对象是否属于某一类型,而不是获取的对象的类型。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。 js中的数据类型 js中只有六种原始数据类型和一个Object: Boolean Null Undefined Number String Symbol ...

    voyagelab 评论0 收藏0
  • JavaScript之深入各种继承

    摘要:通常有这两种继承方式接口继承和实现继承。理解继承的工作是通过调用函数实现的,所以是寄生,将继承工作寄托给别人做,自己只是做增强工作。适用基于某个对象或某些信息来创建对象,而不考虑自定义类型和构造函数。 一、继承的概念 继承,是面向对象语言的一个重要概念。通常有这两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。 《JS高程》里提到:由于函数没有签名,...

    tomlingtm 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<