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)
相关推荐
RadiumAg38 分钟前
记一道有趣的面试题
前端·javascript
yangzhi_emo42 分钟前
ES6笔记2
开发语言·前端·javascript
yanlele1 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
烛阴2 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
初遇你时动了情3 小时前
腾讯地图 vue3 使用 封装 地图组件
javascript·vue.js·腾讯地图
dssxyz3 小时前
uniapp打包微信小程序主包过大问题_uniapp 微信小程序时主包太大和vendor.js过大
javascript·微信小程序·uni-app
ohMyGod_1235 小时前
React16,17,18,19新特性更新对比
前端·javascript·react.js
@大迁世界5 小时前
第1章 React组件开发基础
前端·javascript·react.js·前端框架·ecmascript
一瓣橙子5 小时前
7.7日 实验03-Spark批处理开发(2)
开发语言·javascript·ajax
Hilaku5 小时前
从一个实战项目,看懂 `new DataTransfer()` 的三大妙用
前端·javascript·jquery