js各种继承方式汇总
时间:2022-05-06
本文章向大家介绍js各种继承方式汇总,主要内容包括js中的各种继承实现汇总、构造继承(使用call、apply方式)、实例继承、复制继承或拷贝继承(暴力继承)、对象冒充继承(类似于构造继承)、组合继承(构造继承+原型链继承)、寄生组合继承、ES6的class继承、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
js中的各种继承实现汇总
首先定义一个父类:
function Animal(name) {
this.name = name || '动物'
this.sleep = function () {
console.log(this.name + '正在睡觉!')
}
}
Animal.prototype.eat = function (food) {
console.log(this.name + '正在吃:' + food)
}
原型链继承
特点: 1、子类的原型指向父类的实例 缺点: 1、无法多继承 2、无法向父类的构造传参 3、来自原型对象的引用属性是所有实例共享的
function Cat() { }
Cat.prototype = new Animal()
Cat.prototype.name = '猫'
// Test code
const cat = new Cat()
console.log(cat.name) // 猫
cat.eat('鱼') // 猫正在吃:鱼
cat.sleep() // 猫正在睡觉!
console.log(cat instanceof Cat) // true
console.log(cat instanceof Animal) // true
构造继承(使用call、apply方式)
特点: 1、子类的构造中进行父类构造的调用 优点: 1、实现了多继承,想继承哪个直接在子类构造里面call或者apply哪个就行 2、避免所有子类实例共享父类引用属性问题 3、创建子类实例时,可以向父类传递参数 缺点: 1、没用到原型,只是单纯继承了父类的实例属性及方法 2、没继承原型上的属性及方法 3、每个子类都有父类方法属性的副本,影响性能,没有实现父类函数复用
function Dog(name) {
Animal.call(this)
this.name = name || '狗'
}
// Test code
const dog = new Dog()
console.log(dog.name) // 狗
dog.sleep() // 狗正在睡觉!
// dog.eat('粑粑') 不能继承原型上的eat
console.log(dog instanceof Dog) // true
console.log(dog instanceof Animal) // false,等于是复制父类的实例属性给子类,没用到原型
实例继承
特点: 1、子类的构造中返回父类的实例 优点: 1、可以继承原型上的属性或方法 缺点: 1、实例为父类实例,而非子类实例 2、不能实现多继承
function Pig(name) {
const instance = new Animal()
instance.name = name || '猪'
return instance
}
// Test code
const pig = new Pig()
console.log(pig.name) // 猪
pig.sleep() // 猪正在睡觉!
pig.eat('菠菜叶子') // 猪正在吃:菠菜叶子
console.log(pig instanceof Pig) // false
console.log(pig instanceof Animal) // true
复制继承或拷贝继承(暴力继承)
特点: 1、子类的构造中强制拷贝父类原型上的属性或方法 优点: 1、可以多重继承 缺点: 1、效率较低,内存占用高 2、不能继承父类不可枚举的属性(不能用for in遍历的)
function Rabbit(name) {
const animal = new Animal() // 多重继承直接new多个遍历
for (let i in animal) {
Rabbit.prototype[i] = animal[i]
}
Rabbit.prototype.name = name || '兔子'
}
// Test code
const rabbit = new Rabbit('傻兔子')
console.log(rabbit.name) // 傻兔子
rabbit.sleep() // 傻兔子正在睡觉!
rabbit.eat('胡萝卜') // 傻兔子正在吃:胡萝卜
console.log(rabbit instanceof Rabbit) // true
console.log(rabbit instanceof Animal) // false
对象冒充继承(类似于构造继承)
同构造继承
function Mouse(name) {
this.method = Animal
this.method(name)
delete this.method
}
// Test code
const mouse = new Mouse('老鼠')
console.log(mouse.name) // 老鼠
mouse.sleep() // 老鼠正在睡觉!
// mouse.eat('大米') // 继承不到原型上的属性
console.log(mouse instanceof Mouse) // true
console.log(mouse instanceof Animal) // false
组合继承(构造继承+原型链继承)
特点: 1、组合构造继承和原型链继承 优点: 1、可以继承实例属性/方法,也可以继承原型属性/方法 2、既是子类的实例,也是父类的实例 3、不存在引用属性共享问题 4、可传参 5、函数可复用 缺点: 1、调用了两次父类构造函数
function Duck(name) {
Animal.call(this, name)
}
Duck.prototype = new Animal()
Duck.prototype.say = function () { // 新增的say方法
console.log(this.name + '正在说话!')
}
// Test code
const duck = new Duck('鸭子')
console.log(duck.name) // 鸭子
duck.sleep() // 鸭子正在睡觉!
duck.eat('虫子') // 鸭子正在吃:虫子
console.log(duck instanceof Duck) // true
console.log(duck instanceof Animal) // true
寄生组合继承
特点: 1、使用中间函数对象避免父类构造被两次调用的问题 优点: 1、完美 缺点: 1、写起来费劲
function Snake(name) {
Animal.call(this, name)
}
const Super = function () { }
Super.prototype = Animal.prototype
Snake.prototype = new Super()
// Test code
const snake = new Snake('蛇')
console.log(snake.name) // 蛇
snake.sleep() // 蛇正在睡觉!
snake.eat('小鸟') // 蛇正在吃:小鸟
console.log(snake instanceof Snake) // true
console.log(snake instanceof Animal) // true
ES6的class继承
class Point {
constructor(x, y) { //constructor 构造方法
this.x = x
this.y = y
}
toString() {
return this.x + ', ' + this.y
}
static hello() {
console.log('hello world!')
}
}
class ColorPoint extends Point {
constructor(x, y, color){
super(x, y) // 必须先调用super,否则子类的this不可用
this.color = color
}
toString() {
return this.color + ',' + super.toString()
}
}
// Test code
const cp = new ColorPoint(25, 8, 'green')
console.log(cp instanceof ColorPoint) // true
console.log(cp instanceof Point) // true
ColorPoint.hello() // hello world!
- 数据库分库分表中间件 Sharding-JDBC 源码分析 —— SQL 路由(二)之分库分表路由
- [喵咪开源软件推荐(3)]全球IP库-GeoLite2-City
- [喵咪MQ(3)]RabbitMQ集群安装配置
- 动态实现指定图片半透明及鼠标事件
- JVM杂谈之JIT
- 熔断器 Hystrix 源码解析 —— 执行结果缓存
- [喵咪MQ(2)]RabbitMQ单机模式使用
- [喵咪MQ(1)]RabbitMQ简单介绍准备工作
- Dubbo 源码解析 —— Directory
- [喵咪大数据]Hbase搭建和基本使用
- CSS:模拟Windows窗口及DIV居中
- [喵咪大数据]Hive2搭建和基本操作
- [喵咪大数据]Hadoop节点添加下线和磁盘扩容操作
- [喵咪大数据]Hadoop集群模式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- java编程思想第四版第六章习题
- Docker部署Python项目
- 03 . 二进制部署kubernetes1.18.4
- 01 . 美团全链路监控CAT简介及部署
- 02 . Ansible高级用法(运维开发篇)
- java编程思想第四版第七章总结
- OpenVPN原理及部署使用
- 04 . Jenkins部署Java项目
- java编程思想第四版第七章习题
- 03 . Jenkins构建之代码扫描
- mysql提示Packet for query is too large (1142 > 1024)解决方案
- Kubernetes 1.19.0——deployment(1)
- 02 . Jeknins简介部署及自动化部署PHP代码
- java编程思想第四版第八章习题
- java编程思想第四版第八章总结