js中继承关系杂乱?这篇带你理清

原型链继承

  • 每个构造函数都有一个原型对象prototype ,每个实例对象包含一个指向原型对象的指针proto,当代码读取实例的某个属性时,会首先在实例上搜索这个属性,如果没找到,则会去搜索原型对象。
  • 缺点:包含引用类型的值的原型属性会被所有实例共享,如果一个实例改变了这个属性,那么其他实例的该属性也会被改变
js 复制代码
//原型链继承
function Animal(){
    this.arr=[1,2,3]
}
function Cat(){
}
Cat.prototype=new Animal()
var cat1=new Cat()
var cat2=new Cat()
cat1.arr.unshift(4)
console.log(cat1.arr)//[ 4, 1, 2, 3 ]
console.log(cat2.arr)//[ 4, 1, 2, 3 ]
js 复制代码
//原型链继承
----------------写法一
function Animal(name){
    this.name=name
}
Animal.prototype.run=function(){
    console.log(this.name+'跑得快')
}
function Cat(name){
    this.name=name
}
Cat.prototype=new Animal()
var cat1=new Cat("小花")
cat1.run()//小花跑得快
js 复制代码
//原型链继承
----------------写法二
function Animal(){
    this.name="11"
}
Animal.prototype.run=function(){
    return this.name
}
function Cat(){
    this.name="12"
}
Cat.prototype=new Animal()
var cat1=new Cat()
console.log(cat1.run())//12

构造函数继承

  • 构造函数继承,通过使用call或者apply方法,可以在子类中执行父类的构造函数,实现继承
  • 优点:原型属性不会被共享
  • 缺点:不会继承父类prototype上的属性(注意父类的方法还是可以继承的)
js 复制代码
//构造函数继承
function Animal(){
    this.arr=[1,2,3]
}
Animal.prototype.aa="我是父类prototype上的属性"
function Cat(){
    Animal.call(this)
}
var dog=new Animal()
var cat1=new Cat()
var cat2=new Cat()
cat1.arr.unshift(4)
console.log(cat1.arr)//[ 4, 1, 2, 3 ]
console.log(cat2.arr)//[ 1, 2, 3 ]
console.log(dog.aa);//我是父类prototype上的属性
console.log(cat1.aa);//undefined

组合式继承(为了解决构造函数继承无法继承父类prototype的问题)

  • 优点:原型属性不会被共享
  • 可以继承父类的原型链上的属性和方法
  • 缺点:调用了两次父类
  • 在子类的prototype上添加了父类的属性和方法
js 复制代码
//组合式继承
function Animal(){
    this.arr=[1,2,3]
}
Animal.prototype.aa="我是父类prototype上的属性"
function Cat(){
    Animal.call(this)
}
var dog=new Animal()
Cat.prototype=new Animal()--------------在构造函数继承上加入这一行代码
var cat1=new Cat()
var cat2=new Cat()
cat1.arr.unshift(4)
console.log(cat1.arr)//[ 4, 1, 2, 3 ]
console.log(cat2.arr)//[ 1, 2, 3 ]
console.log(dog.aa);//我是父类prototype上的属性
console.log(cat1.aa);//我是父类prototype上的属性

寄生组合继承

  • 优点:原型属性不会被共享
  • 可以继承父类的原型链上的属性和方法
  • 只调用了一次父类,不会在子类的prototype上添加父类的属性和方法
  • 缺点:子类的prototype的原始属性和方法会丢失
  • 解决:放到Object.create后面执行
js 复制代码
//寄生组合继承
function Animal(){
    this.arr=[1,2,3]
}
Animal.prototype.aa="我是父类prototype上的属性"
function Cat(){
    Animal.call(this)
}
Cat.prototype.run=()=>{
    console.log('跑');
}
//创建的是一个没有实例方法的父类实例作为子类的原型
//但是寻找的时候会去有实例方法的父类原型上找
Cat.prototype=Object.create(Animal.prototype)
//指定构造函数的指向
Cat.prototype.constructor=Cat
var cat1=new Cat()
cat1.run()//error
cat1.arr.unshift(4)
console.log(cat1.arr)
相关推荐
To_OC6 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
小林ixn8 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
窝子面10 小时前
手搓最简前后端协作-node
javascript·数据库
kyriewen11 小时前
我让AI给前端项目做了一次完整的Code Review——它和人类的差距,比我想的大得多
前端·javascript·ai编程
এ慕ོ冬℘゜12 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
sugar__salt13 小时前
Vue3 表单双向绑定与响应式核心 API 技术详解
前端·javascript·vue.js
SmartBoyW13 小时前
CSS弹性布局(Flexbox)学习笔记:从零开始搞懂弹性布局
前端·javascript
用户9385156350713 小时前
写了这么久 useState,你真的知道它在干什么吗?
前端·javascript
烬羽14 小时前
递归老写崩?一个"退回"公式,把回溯题变成填空题
javascript·深度学习·算法
浮江雾15 小时前
Flutter第十七节-----路由管理(3)
android·开发语言·前端·javascript·flutter·入门