首页 > 编程语言 >关于 Javascript 的几种继承

关于 Javascript 的几种继承

时间:2023-03-04 17:00:46浏览次数:46  
标签:function prototype Parent 继承 Javascript 几种 原型 属性 构造函数

原型链的概念:

原型链通俗易懂的理解就是可以把它想象成一个链条,互相连接构成一整串链子

而原型链中就是实例对象和原型对象之间的链接

每个函数都有一个prototype属性,这个prototype属性就是我们的原型对象,我们拿这个函数通过new构造函数创建出来的实例对象,这个实例对象自己会有一个指针(_proto_)指向他的构造函数的原型对象

这样构造函数和实例对象之间就通过( _proto_ )连接在一起形成了一条链子

prototype,用来实现基于原型的继承与属性的共享

避免了代码冗余,公用的属性和方法,可以放到原型对象中,这样,通过该构造函数实例化的所有对象都可以使用该对象的构造函数中的属性和方法!同时减少了内存占用

继承方式:

  • 原型链继承

缺点:Parent 中的引用属性会被每个子类实例共享,以及继承过多 Parent 中定义过的属性

function Parent() {
    this.parentPrototype = "parent prototype"
    //验证这种继承方法的确定,如果父类示例中存在一个引用类型的属性,将会被所有子类共享
    this.parentObj = {
         info: "我是 parent 引用属性parentObj中的 info"
    }
}
function Children() {
}
//将Children的原型对象指定为Parent的实例,通过原型链,将Parent中的属性赋值给Children实例
Children.prototype = new Parent();
const a = new Children();
console.log(a.parentPrototype); // parent prototype
//缺点
const b = new Children();
//在a示例中改动继承的引用属性
a.parentObj.info = "我是a实例中 引用属性parentObj中的 info"
//b与a示例共享引用属性
console.log(b.parentObj.info); // 我是a实例中 引用属性parentObj中的 info
  • 借用构造函数继承

优点:1.避免了子类实例共享引用属性的情况;2.可以在实例化时给Parent构造函数传递参数

缺点:如果Parent中存在一个函数,那么每次实例化Children的时候,都会创建一个同样函数,函数的复用性就难以体现

function Parent() {
    this.parentPrototype = "parent prototype"
    this.obj = {
         info: "parent obj info"
    }
     this.fn = function () {
        console.log("打印功能")
    }
}
// 在子类构造函数内部调用父类的构造函数,需要使用call绑定上下文 function Children() { Parent.call(this); } const a = new Children(); console.log(a.parentPrototype); // parent ptototype //缺点 此时Parent()会再次创建一个fn函数,这个是没有必要的 const b = new Children(); a.obj.info = "a obj info"; //优点 避免了子类实例共享引用属性 console.log(b.obj.info) // parent obj info;
  • 组合继承(原型链 + 构造函数)--常用的继承方式

优点:避免了子类实例共享引用属性,同时避免了父类构造函数重复对function属性的创建

function Parent() {
    this.parentPrototype = "我是Parent 中的属性"
}
//Parent中的方法,在原型上定义
Parent.prototype.pFn = function () {
    console.log('我是Parent中的方法');
}
function Children() {
    //Parent中的属性仍然在构造函数中继承
    Parent.call(this);
}
//将Children的原型对象赋值为 Parent实例,这样Parent中的方法也能够被Children继承
Children.prototype = new Parent();
const c = new Children();
console.log(c.parentPrototype); //我是Parent 中的属性
c.pFn(); //我是Parent中的方法
  • 原型式继承

缺点:和原型链继承一样,后代实例会共享父类引用属性

function objFn(o) {
    o.objFnPrototype = "我是 objFnPrototype"
    function F() {}
    F.prototype = o;
    return new F();
}
let a = objFn({
    name: "name1"
});
console.log(a.name); //name1
console.log(a.objFnPrototype); //我是 objFnPrototype

  

  • 寄生继承

缺点:和原型链继承一样,parent中的引用属性,会被所有示例共享

function createObje(obj) {
    let clone = Object.assign(obj); //接受到对象后,原封不动的创建一个新对象
    clone.prototype1 = "我是新增的prototype1"; //在新对象上新增属性,这就是所谓的寄生
    return clone; //返回新对象
}
const parent = {
    parentPrototype: "parentPrototype"
}
//c实例,就继承了parent的所有属性
let c = createObje(parent);
console.log(c.parentPrototype); //parentPrototype

  

  • 寄生组合继承(寄生 + 组合)

优点:和组合继承一样,只不过没有组合继承的调用两次父类构造函数的缺点

function inherProto(superType, subType) {
    //拷贝一个超类的原型副本
    let proto = {
       ...superType.prototype
    };
    //将原型的超类副本作为子类的原型对象,也就是第一种中的原型链继承方式,只不过继承的是超类原型的副本
    subType.prototype = proto;
    //这一步比较迷,官方的说法是,我们在拷贝超类的原型的时候,拷贝的proto对象,将会丢失默认自己的构造函数,也就是superType,
    //所以我们这里将它的构造函数补全为subType。貌似不做这一步也没啥问题,但是缺了点东西可能会有其他的副作用,所以还是补上
    proto.constructor = subType;
}
function Super() {
    this.superProto = "super proto";
    this.colors = ["red", "yelloy"];
}
function Sub() {
    this.subProto = "sub proto";
    this.name = "sub name";
    //这里还是借用构造函数的套路
    Super.call(this);
}
Super.prototype.getName = function () {
    console.log(this.name);
}
//这里要在定义完Super的属性后执行,因为继承的是超类原型的副本,与Super.prototype是两个对象,在这之后再改变Super.prototype,就已经不会在影响到Sub所继承的副本超类原型对象了
inherProto(Super, Sub);
let a = new Sub();
console.log(a.getName);

引用:

https://www.cnblogs.com/wrhbk/p/14477637.html

https://blog.csdn.net/qq_51486722/article/details/122863959

标签:function,prototype,Parent,继承,Javascript,几种,原型,属性,构造函数
From: https://www.cnblogs.com/Du9191/p/17178385.html

相关文章

  • JavaScript Modal Image
    <!DOCTYPEhtml><html><head><title>JavaScriptModalImage</title></head><styletype="text/css"> .modal{ position:fixed; z-index:1......
  • 4.this的原理以及几种不同使用场景的取值
    1.this原理this是JavaScript的一个关键字,函数调用时才会出现;因为函数是在一定的环境中运行的,调用函数时肯定需要知道是[谁调用的]?就用到了this进行指向;那么this到底指向的......
  • 3.理解JavaScript的执行上下文、执行上下文栈,可以应用堆栈信息快速定位问题
    1.执行上下文执行上下文就是当前JavaScript代码被解析和执行时所在环境的抽象概念,JavaScript中运行任何的代码都是在执行上下文中运行1.执行上下文的类型全局执行......
  • 2.理解JavaScript的作用域和作用域链
    什么是作用域Javascript中的作用域说的是变量的可访问性和可见性。也就是说整个程序中哪些部分可以访问这个变量,或者说这个变量都在哪些地方可见。作用域的类型全局作......
  • 4.理解es6 class构造以及继承的底层实现原理
    javascript使用的是原型式继承,我们可以通过原型的特性实现类的继承,es6为我们提供了像面向对象继承一样的语法糖。1.类的实现class底层仍然是构造函数调用_classCallChe......
  • 实现js继承的几种方式以及他们的优缺点
    7.实现继承的几种方式以及他们的优缺点①类式继承(构造函数) varfather=function(){  this.age=52;  this.say=function(){   alert('helloiam'......
  • JavaScript中Date对象
    当我们收到甲方的需求,要做一个类似于商城之类的项目的时候,JS的Date对象就至关重要了.因为在商城中,各种优惠和折扣,就需要在一个时间的紧迫下,才能达到一个火爆的效果,......
  • 继承中构造方法的访问特点
    1.子类中所有的构造方法都会默认会访问父类中的无参构造方法 2.每个子类的构造方法的第一句默认是:super()3.因为子类会继承父类中的数据,可能还会使用父类中的数据,所以子......
  • C#获取串口的几种方式
    摘要使用C#获取串口最简单的方式就是通过SerialPort对象了,但有时并不能满足需求,比如有些串口是通过驱动模拟的,那这种可能就获取不到了。示例代码这里简单演示几种常用的......
  • JS文件的几种格式之间的区别
    今天在修改公司ui组件库的时候,接触到npmrunlib,发现打包后文件有几种格式的文件。.common.js.common.js.map.umd.js.umd.js.map.umd.min.js.umd.min.js.map几种不......