JS继承详解

JavaScript】寄生组合继承详解 寄生组合继承是一种改进版的组合继承,它通过解决了Parent构造函数调用两次的问题,使得 JavaScript 继承更加高效。尽管 ES6 的class语法在现代开发中更常见,但理解寄生组合继承的原理有助于深入掌握 JavaScript继承机制。 阅读详情

JS继承主要有以下几种:

1.原型链继承:将父类的实例作为子类的原型

function Parent() {
   this.isShow = true
   this.info = {
      name: "yhd",
      age: 18,
   };
}

Parent.prototype.getInfo = function() {
   console.log(this.info);
   console.log(this.isShow); // true
}

function Child() {};
// 最关键的一行
Child.prototype = new Parent();

2.构造函数继承:通过在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call()apply()方法。

function Parent() {
  this.info = {
    name: "yhd",
    age: 19,
  }
}

function Child() {
// 通过 call 方法将 child构造函数调用时产生的实例对象作为parent的函数上下文
,因此继承了parent的引用属性info。
    Parent.call(this)
}

let child1 = new Child();
child1.info.gender = "男";
console.log(child1.info); // {name: "yhd", age: 19, gender: "男"};

let child2 = new Child();
console.log(child2.info); // {name: "yhd", age: 19}

通过使用这两个方法,Parent构造函数在 new 一个 child 实例对象的上下文中执行了,就相当于新创建的实例对象运行了 Parent()函数中的所有初始化代码,结果就是每个实例都有自己的info属性。

优点:对比原型链继承,构造函数继承的一个优点是子类构造函数可以向父类构造函数传参;父类的的引用属性不会被共享

缺点:子类不能访问父类原型上的方法,(即不能访问Parent.prototype上定义的方法),因此所有方法属性都写在构造函数中,每次创建实例都会初始化

function Parent(name) {
    this.info = { name: name };
}
function Child(name) {
    //继承自Parent,并传参
    Parent.call(this, name);
    
     //实例属性
    this.age = 18
}

let child1 = new Child("yhd");
console.log(child1.info.name); // "yhd"
console.log(child1.age); // 18

上面实例中得知,父类构造函数Parent接受到一个参数name,并将它赋值给属性name,在Child构造函数中调用 Parent构造函数时传入这个参数,实际上会在Child实例上定义name属性。

3.组合继承

结合原型链继承和构造函数继承的优点:基本思路是使用原型链继承原型上的属性和方法,使用构造函数继承实例属性。

function Parent(name) {
   this.name = name
   this.colors = ["red", "blue", "yellow"]
}
Parent.prototype.sayName = function () {
   console.log(this.name);
}

function Child(name, age) {
   // 继承父类属性
   Parent.call(this, name)
   this.age = age;
}
// 继承父类方法
Child.prototype = new Parent();

Child.prototype.sayAge = function () {
   console.log(this.age);
}

let child1 = new Child("yhd", 19);
child1.colors.push("pink");
console.log(child1.colors); // ["red", "blue", "yellow", "pink"]
child1.sayAge(); // 19
child1.sayName(); // "yhd"

let child2 = new Child("wxb", 30);
console.log(child2.colors);  // ["red", "blue", "yellow"]
child2.sayAge(); // 30
child2.sayName(); // "wxb"

从上面的例子可知,Parent构造函数定义了两个属性name和colors,然后在他的原型上定义了sayName()方法,Child 构造函数内部调用了 Parent 构造函数,同时传入了参数name,同时Child.prototype也被赋值为Parent实例,然后又在他的原型上添加了个sayAge()方法。

这样就创建了两个实例child1 child2,让两个实例都有自己的属性,而且还共享了父类的sayName方法。

总结:组合类继承的优点有三个,父类的方法可以共用、父类构造函数的引用属性不会共享、子类构造函数可以传参。

4.原型式继承

对参数对象的一种浅复制

// 在普通函数里面调用构造函数创建一个实例对象,并将被复制对象作为参数,赋值给这个实例对象,
从而实现继承
function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun()
}

let person = {
  name: "yhd",
  age: 18,
  friends: ["jack", "tom", "rose"],
  sayName:function() {
    console.log(this.name);
  }
}

let person1 = objectCopy(person);
person1.name = "wxb";
person1.friends.push("lily");
person1.sayName(); // wxb

let person2 = objectCopy(person);
person2.name = "gsr";
person2.friends.push("kobe");
person2.sayName(); // "gsr"

console.log(person.friends); // ["jack", "tom", "rose", "lily", "kobe"]

缺点:父类的引用属性会被共享(例子中的friends)、子类不能向父类传参。

5.寄生式继承

使用原型式继承实现对目标对象的浅复制,同时增强浅复制的能力

function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}

function createAnother(original) {
  let clone = objectCopy(original);
  clone.getName = function () {
    console.log(this.name);
  };
  return clone;
}

let person = {
     name: "yhd",
     friends: ["rose", "tom", "jack"]
}

let person1 = createAnother(person);
person1.friends.push("lily");
console.log(person1.friends); // ["rose", "tom", "jack", "lily"]
person1.getName(); // yhd

let person2 = createAnother(person);
console.log(person2.friends); // ["rose", "tom", "jack", "lily"]

6.寄生式组合继承(是引用类型继承的最佳模式 )

function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}

function inheritPrototype(child, parent) {
  let prototype = objectCopy(parent.prototype); // 创建对象

  // 这两行代码形成闭环,prototype上的属性constructor指向child构造函数,child构造函数
  上的属性prototype 指向它的原型prototype对象

  prototype.constructor = child; // 增强对象
  Child.prototype = prototype; // 赋值对象
}

function Parent(name) {
  this.name = name;
  this.friends = ["rose", "lily", "tom"]
}

Parent.prototype.sayName = function () {
  console.log(this.name);
}

function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}

//与组合继承的区别在于这一句代码
inheritPrototype(Child, Parent);

// 在组合式继承中,是继承父类方法
// Child.prototype = new Parent();

Child.prototype.sayAge = function () {
  console.log(this.age);
}

let child1 = new Child("yhd", 23);
child1.sayAge(); // 23
child1.sayName(); // yhd
child1.friends.push("jack");
console.log(child1.friends); // ["rose", "lily", "tom", "jack"]

let child2 = new Child("yl", 22)
child2.sayAge(); // 22
child2.sayName(); // yl
console.log(child2.friends); // ["rose", "lily", "tom"]

优点:

  1. 父类的方法可以复用

  2. 可以在Child构造函数中向Parent构造函数中传参

  3. 父类构造函数中的引用属性不会被共享

  4. 只调用一次构造函数

JavaScript中的继承与原型链详解 同理,原型对象也是一个对象,它也有自己的原型对象,因此也可以继承它的原型对象的属性。这样的实现避免了引用类型的属性被所有实例共享的问题,在父类实例创建时还可以自定义地传参,缺点是方法都是在构造函数中定义,每次创建实例都会重新赋值一遍方法,即使方法的引用是一致的。在访问一个对象的时候,JavaScript 引擎会执行一个搜索过程,如果在对象实例上发现该属性,该属性值就会被使用,如果没有发现则搜索其原型对象。这就是原型继承链:对象继承其原型对象,而原型对象继承它的原型对象,以此类推。 阅读详情

相关推荐

Codex入门00-初识神器(小白入门:到底什么是Codex CLI,和ChatGPT写代码有什么不同?)

OpenAI Codex CLI 是 OpenAI 于2025年推出的终端原生AI编程代理,不是在网页里聊天写代码,而是直接在你的终端里自主读代码、改文件、跑命令。它拥有三种安全模式、/goal 持久化任务、云端沙箱执行等独特能力。本文从零介绍 Codex CLI 的核心概念、与 ChatGPT 写代码的本质区别、典型使用场景和费用说明,让你全面认识这个改变开发方式的神器。

yueyeguzhuo的专栏 245

JS中的八种继承方法

详细讲解js中的八种继承方法,原型链继承、构造函数继承(经典继承)、组合面试、原型式继承、Object.create()、寄生式继承、寄生组合式继承、ES6类继承

weixin_70134200的博客 6631

OSError We couldn‘t connect to https://huggingface.co to load file, couldn‘t find it chatglm3-6b解决方案

本文主要介绍了OSError: We couldn’t connect to https://huggingface.co to load this file, couldn’t find it in the cached files and it looks like THUDM/chatglm3-6b is not the path to a directory containing a file named config.json.解决方案,希望能对学习python的同学们有所帮助。

weixin_43178406的博客 5万+

Js实现继承的6种方式

Js实现继承的6种方式: 1.原型链继承 2.借用构造函数继承 3.组合继承(经典继承) 4.原型式继承 方法一: 方法二:Object.create() 5.寄生式继承 6.寄生组合式继承 7.ES6、Class实现继承

wuliyouMaozhi的博客 2万+

【笔记】JS实现继承的几种方式

JS实现继承的几种方式

weixin_44755080的博客 2683

js的六种继承方式

1、原型链继承 核心: 将父类的实例作为子类的原型 特点: 1.非常纯粹的继承关系,实例是子类的实例,也是父类的实例 2.父类新增原型方法/原型属性,子类都能访问到 3.简单,易于实现缺点: 1.要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中 2.无法实现多继承 3.来自原型对象的所有属性被所有实例共享(来自原型对象的引用属性是所有实例共享的) 4.创建子类实例时,无法向父类构造函数传参2、构造函数继承(借助 call) 核心:使用父类的构造函数来增强子类实例

weixin_41759744的博客 7732

JavaScript继承

寄生组合继承存在效率问题,最主要的效率问题是父类构造函数始终被调用两次,一次是在创建子类原型时调用,另一次是在子类构造函数中调用,本质上,子类原型最终是要包含超类对象的所有实例属性,子类构造函数只要在执行的时候重写自己的原型就可以了。把子类的原型对象指向父类,就能使用父类中的方法和属性了。采用原型式继承不自定义类型,临时创建一个构造函数,借助已有的对象作为临时构造函数的原型,然后在此基础实例化对象,并返回。继承就是指一个子类继承父类的属性和方法,使得子类对象(实例化对象)具有父类的方法和属性。

m0_61480985的博客 1982

jsjavascript)实现继承的6种方式以及优缺点详解

js继承的6种方式 想要继承,就必须要提供个父类(继承谁,提供继承的属性)      一、原型链继承      重点:让新实例的原型等于父类的实例。     特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属性。(新实例不会继承父类实例的属性!)     缺点:1、新实例无法向父类构造函数传参。        2、继承单一。        3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)      二、

m0_53592673的博客 2199

php中 继承中的概念,JavaScript_JavaScript中的继承方式详解js继承的概念 js里常用的如下 - phpStudy...

JavaScript中的继承方式详解js继承的概念js里常用的如下两种继承方式:原型链继承(对象间的继承)类式继承(构造函数间的继承)由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。所以,要想实现继承,可以用js的原型prototype机制或者用apply和call方法去实现在面向对象的语言中,我们使用类来创建一个自定义对象。然而js中所有事物都是对象,那么用什么办...

weixin_39636696的博客 126

JavaScript继承方式详解

博文中介绍了JavaScript中实现继承的几种方式,详细介绍了其中的原型链、借用构造函数、组合继承以及原型式继承

诗渊的博客 4951

详解js继承

详解js继承 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录详解js继承前言一、预备知识1.构造函数的属性2.什么是原型对象3.原型对象的作用二、五种js继承方式方式1、原型链继承方式2、借用构造函数方式3、组合继承总结 前言 最近在复习准备面试题,这里记录一下关于js继承。 一、预备知识 1.构造函数的属性 function A(name){ this.name = name; //实例基本属性(该属性强调私有 不共享) this.arr = [1]; //实例引用属

yan的秘密基地 1663

JavaScript 继承方式详解

JavaScript提供了多种继承方式:1)原型链继承简单但共享引用属性;2)构造函数继承可传参但无法继承原型方法;3)组合继承结合两者优势;4)原型式继承基于现有对象;5)寄生式继承扩展原型式方法;6)寄生组合式继承是最理想的实现方式;7)ES6的class继承语法更清晰。推荐使用寄生组合式继承或ES6 class继承,它们既高效又避免了常见缺陷,是JavaScript面向对象编程的最佳实践。

qq_46032105的博客 1474

javascript中的继承详解

1 原型链继承 父类的实例作为子类的原型 function Woman(){ } Woman.prototype= new People(); Woman.prototype.name = 'haixia'; let womanObj = new Woman(); 优点:简单易于实现,父类的新增的实例与属性子类都能访问 缺点:可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面 无法实现多继承 创建子类实例时,不能向父类构造函数中传参数 2.借用构造函数继承(伪造对象、

FengYang_的博客 192

JavaScript继承的实现方式详解

继承方式主要特点优点缺点原型链继承让子类prototype指向父类实例方法共享共享引用属性构造函数继承使用call调用父类解决共享问题,可传参方法无法复用组合继承构造函数 + 原型链解决共享问题调用两次父类构造函数寄生组合继承最优 ES5 方案解决所有问题代码略复杂ES6class继承最现代化方案语法简洁,推荐使用仅限 ES6+在现代 JavaScript 开发中,建议优先使用 ES6class继承,但在需要兼容旧浏览器时,可以使用寄生组合继承

lph159的博客 2161

JavaScript继承详解

继承 概念解析 继承的方式 继承的意义

KaiSarH 557

JavaScript继承方式详解

转自:http://segmentfault.com/a/1190000002440502 js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念。所以,要想实现继承,可以用js的原型prototype机制或者用apply和call方法去实现 ...

banfu7150的博客 93

JavaScript继承详解

http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html  一、sanshi   javascript 继承系列:1、   JavaScript继承详解(一)    http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 2、JavaScript

livening的专栏 447

js中的继承详解

js中的继承 假设我们有一个Animal类,我们想构造Cat类,Cat类可以继承Animal类的属性和方法。以这个场景为列,我来讲一讲我所理解的js继承。 构造继承 function Animal(name){ this.name = name; this.age = 15; } function Cat(name){ Animal.call(this, name); th...

izwell的博客 2324

JavaScript 继承模式图文详解

JavaScript 继承模式 文章目录JavaScript 继承模式原型链继承借用构造函数继承组合继承 原型链继承 我们知道在JavaScript中,对象的继承时依靠原型来进行,那么原型到底是如何进行继承的呢? 如果有关原型的内部不是很清楚的,可以看一下https://blog.csdn.net/weixin_45845042/article/details/106121200 现在让我们来看一下,JavaScript中原型到底是如何进行继承的 function Sub(name,age) { t

weixin_45845042的博客 385

Oracle11g客户端32位

Oracle11g客户端32位;只有70多m,具有完整版的大多数功能,配合plsql使用

上一篇: 原型与原型链详解
winterjoycc
博客等级 码龄8年 12粉丝 · 18原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值