js实现继承的多种方式

1. 原型链继承

function Parent() {
this.name = 'xwk'
}
Parent.prototype.getName = function() {
console.log(this.name)
}
function Child() {}
Child.prototype = new Parent()
var child = new Child()
console.log(child.getName()) // xwk

缺点:

  1. 引用类型的属性被所有实例共享,举个例子:
function Parent () {
this.names = ['kevin', 'daisy'];
}
function Child () {}
Child.prototype = new Parent();
var child1 = new Child();
child1.names.push('yayu');
console.log(child1.names); // ["kevin", "daisy", "yayu"]
var child2 = new Child();
console.log(child2.names); // ["kevin", "daisy", "yayu"]
  1. 在创建Child的实例时,不能向Parent传参数
  2. 实例丢失了自己的construct属性

2. 经典继承(借用构造函数(使用call))

function Parent() {
this.names = ["kevin", "daisy"]
}
Parent.prototype.getName = function() {
console.log(this.names)
}
function Child() {
Parent.call(this)
}
var child1 = new Child()
child1.names.push('yayu');
console.log(child1.names); // ["kevin", "daisy", "yayu"]
var child2 = new Child();
console.log(child2.names); // ["kevin", "daisy"]

缺点:Parent原型上的属性和方法不能被继承

优点:

  1. 在继承的时候可以向Parent传参
  2. 可以避免引用类型的属性被不同实例所共享

3. 组合继承

原型链继承 + 经典继承

function Parent(name) {
this.name = name
this.colors = ['red','blue']
}
Parent.prototype.getName = function() {
console.log(this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
Child.prototype = new Parent()
Child.prototype.constructor = Child var child1 = new Child('kevin', '18'); child1.colors.push('black'); console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"] var child2 = new Child('daisy', '20'); console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

分析下上述代码:

  1. Parent.call(this, name) ,解决了传参问题,并且将Parent构造函数内的属性复制到Child里,可以避免引用类型被共享;
  2. Child.prototype = new Parent() 同时使用原型链继承,可以保证Parent原型上的属性和方法能被Child继承到。

4. 原型式继承 (Object.create)

function createObj(obj) {
function F() {}
F.prototype = obj
return new F()
}

上述代码,其实就是ES5 Object.create 方法的实现,将传入的对象作为一个新对象的原型返回。

缺点:和原型链继承的缺点一样,引用类型的属性会被子实例所共享

var person = {
name: 'kevin',
friends: ['daisy', 'kelly']
} var person1 = createObj(person);
var person2 = createObj(person); person1.name = 'person1';
console.log(person2.name); // kevin person1.friends.push('taylor');
console.log(person2.friends); // ["daisy", "kelly", "taylor"]

5. 寄生式继承

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

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

缺点:和经典模式一样,方法都在构造函数中定义,每次创建实例都会创建一遍方法。

6. 寄生组合继承

其实就是对组合继承的优化,

我们可以看组合继承的代码,发现一共掉了两次Parent构造函数,

一次是Child.prototype = new Parent(),

一次是Child构造函数中,Parent.call(this,name),

这样导致的结果就是Child和Child.prototype中都有colors属性。

那么怎么优化呢,避免这一次重复调用呢?

如果我们不使用 Child.prototype = new Parent() ,而是间接的让 Child.prototype 访问到 Parent.prototype 呢?

function Parent(name) {
this.name = name
this.colors = ['red','blue']
}
Parent.prototype.getName = function() {
console.log(this.name)
}
function Child(name, age) {
Parent.call(this, name)
this.age = age
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child var child1 = new Child('kevin', '18'); child1.colors.push('black'); console.log(child1.name); // kevin
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"] var child2 = new Child('daisy', '20'); console.log(child2.name); // daisy
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

注意️:

使用 Child.prototype = Object.create(Parent.prototype) 替换

Child.prototype = new Parent()

虽然目的都是一样,让Child.prototype 的原型对象 指向 Parent.prototype,

但是使用后者会把Parent构造函数内部的多余属性也继承过来,前者不会。

基础3:js实现继承的多种方式的更多相关文章

  1. js原生继承几种方式

    js原生继承 js本身并没有继承和类的概念,本质上是通过原型链(prototype)的形式实现的. 1.先写两个构造函数Parent和Child,用于将Child继承Parent function P ...

  2. 23.C++- 继承的多种方式、显示调用父类构造函数、父子之间的同名函数、virtual虚函数

     上章链接: 22.C++- 继承与组合,protected访问级别 继承方式 继承方式位于定义子类的”:”后面,比如: class Line : public Object //继承方式是publi ...

  3. JavaScript是如何实现继承的(六种方式)

    大多OO语言都支持两种继承方式: 接口继承和实现继承 ,而ECMAScript中无法实现接口继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现,下文给大家技术js实现继承的 ...

  4. 基础2:js创建对象的多种方式

    js创建对象的多种方式 1. 工厂模式 function createPerson(name) { var o = new Object() 0.name = name return o } var ...

  5. 【编程题与分析题】Javascript 之继承的多种实现方式和优缺点总结

    [!NOTE] 能熟练掌握每种继承方式的手写实现,并知道该继承实现方式的优缺点. 原型链继承 function Parent() { this.name = 'zhangsan'; this.chil ...

  6. js实现继承的5种方式 (笔记)

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

  7. js实现继承的方式总结

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

  8. js实现继承的5种方式

    js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承有以下通用的几种方式1.使用对象冒充实现继承(该种实现 ...

  9. JS中继承方式总结

    说在前面:为了使代码更为简洁方便理解, 本文中的代码均将"非核心实现"部分的代码移出. 一.原型链方式关于原型链,可点击<深入浅出,JS原型链的工作原理>,本文不再重复 ...

随机推荐

  1. Flink使用Pod Template将状态快照(Checkpoint、Savepoint)存储在NFS

    背景 Flink 版本 1.13.3,使用 native k8s 部署模式,原采用 HDFS 作为状态快照(Checkpoint.Savepoint)的存储地址,但是由于仅使用了其 HDFS 作为状态 ...

  2. PostgreSQL 13支持增量排序(Incremental Sorting)

    PostgreSQL 13支持增量排序(Incremental Sorting) PostgreSQL 13一个重要的功能是支持增量排序,使用order by 时可以加速排序,SQL如下 select ...

  3. django框架3

    内容概要 注册登录功能编写 django请求生命周期流程图 路由层相关知识 1.路由匹配 2.无名有名分组 3.反向解析 4.名称空间 5.路由分发 内容详情 注册登录功能编写 1.使用自带的sqli ...

  4. unittest框架里的常用断言方法:用于检查数据

    1.unittest框架里的常用断言方法:用于检查数据. (1)assertEqual(x,y) 检查两个参数类型相同并且值相等.(2)assertTrue(x) 检查唯一的参数值等于True(3)a ...

  5. ElasticSearch7.3学习(三十一)----Logstash基础学习

    一.Logstash基本介绍 Logstash 是一个功能强大的工具,可与各种部署集成. 它提供了大量插件,可帮助你解析,丰富,转换和缓冲来自各种来源的数据(文件.数据库......).logstas ...

  6. .NET Core 企业微信回调配置

    1.配置API接收 2.下载加密解密库 地址:https://developer.work.weixin.qq.com/devtool/introduce?id=36388,也可以复制下面的代码 2. ...

  7. 记一次APP渗透登录验证绕过思路

    前言: 起初是抓包时候查看返回状态码不一致,所以觉得是否可以通过修改状态码来达到绕过的目的,但是拦截响应包再替换手速不够,技术大哥就去搜了下,找到了一个方法,可以自动替换响应包内容. 在偏下方一点的地 ...

  8. 从 CPU 讲起,深入理解 Java 内存模型!

    Java 内存模型,许多人会错误地理解成 JVM 的内存模型.但实际上,这两者是完全不同的东西.Java 内存模型定义了 Java 语言如何与内存进行交互,具体地说是 Java 语言运行时的变量,如何 ...

  9. linux在线安装和配置JDK1.8

    首先在服务器ping www.baidu.com查看是否可以连网 然后就可以在线下载 一.下载安装JDK1.8 1.在下载安装的同时做一些准备工作 我们在usr目录下再创建一个Java文件夹准备放置我 ...

  10. RPA应用场景-对公账户开户资质审查

    场景概述 对公账户开户资质审查 所涉系统名称 人民银行账户管理系统 人工操作(时间/次) 0.5小时 所涉人工数量 132 操作频率 不定时 场景流程 1.机器人自动登录人民银行账户管理系统 2.查询 ...