js的继承01

原型链继承

// 父类
function Person(){
  this.name='zs'
}
// 可以不用写
// Person.prototype.eating(){
//   console.log(this.name+'food')
// }
// 子类
function Student(){
  this.name='看书'
}
const p=new Person()//先使用new创建Person实例
Student.Prototype=p//实例化后的p赋值给子类的显示原型

// 可以不写
// Student.prototyp.reading=function(){
//   console.log(this.name+'阅读')
// }
const stu=new Student()

原型链继承的弊端:

// 第一个弊端:以上面为例,打印stu对象,继承的属性是看不到的
console.log(stu) //需要点开才行

// 第二个弊端:创建出来两个stu对象
  const stu1=new Student()
  const stu2=new Student()
  // 直接修改对象上的属性,是给本对象添加了一个新属性
  stu1.name='ko'
  consoe.lg(stu2.name)
  // 获取引用,修改引用中的值会相互影响
  stu1.arr.push('ko')
  console.log(stu1.arr)
  console.log(stu2.arr)
// 第三个弊端:在前面实现类的过程中都没有传递参数(父类里的值换不了)
const stu=new Student('li')
console.log(stu)
// 为了给父类传值,就用到了借用构造函数继承(call,apply,bind)

原型链继承弊端总体代码:

function Person(){
  this.name='zs'
  // 第二种弊端
  this.arr=[]
}
Person.prototype.eating=function(){
  console.log(this.name+'food')
}
function Student(){
  this.name='读书'
}
const p=new Person()
Student.prototype=p

Student.prototype.reading=function(){
  console.log(this.name+'看书')
}

// 第二种弊端(以下四行代码可都放出来查看效果)
const stu1=new Student()
// const stu2=new Student()
stu1.arr.push('ko')
// stu2.arr.push('ok')
// console.log(stu1,stu2)

// 第三种弊端
const stu=new Student('li')

console.log(stu)

借用构造函数实现继承:

function Person(age, friends) {
  this.age = age
  this.friends = friends
}
function Student(name, friends, sno) {
  Person.call(this, name, friends)
  this.sno = sno
}
var p = new Person()
Student.prototype = p
var stu = new Student(10, ['xxx'], 111)
console.log(stu)

借用构造函数的弊端:

// 子类: 特有属性和方法
function Student(name, age, friends, sno) {
  Person.call(this, name, age, friends)
  this.sno = 111
}

// 直接将父类的原型赋值给子类, 作为子类的原型
Student.prototype = Person.prototype

//为什么不合适?
//这种方案相当于是子类的原型对象就是父类的原型对象, 当给子类添加方法时 ,
// 相当于是全部添加到了父类的原型对象上面。 随着子类的不断增多(Teacher、Student、都可以继承自Person)
// 父类原型对象上的方法也越来越多 相当于所有子类特有的方法都被兄弟类所共享了

寄生组合式继承:

// 父类
function Person(name,friends){
  // this->student对象
  this.name=name
  this.friends=friends
}
Person.prototype.eating(){
  console.log(this.name+'food')
}
// 子类
function Student(name,friends,sno){
  // this->student对象
  Person.call(this,name,friends)
  this.sno=sno
}
// 创建一个子类的原型对象,并让这个原型对象的__proto__指向父类的原型对象
Student.prototype=Object.create(Person.prototype)
// Student.prototypeconstructor=Student

Student.prototyp.reading=function(){
  console.log(this.name+'阅读')
}
const stu=new Student('张三',[],123)
// console.log(stu.__proto__.constructor)

拓展:

默认情况下,所有的原型对象都是由Object所产生的,所以默认情况下,原型对象的隐式原型指向Object.prototype,但是唯独有一个特例:Object的原型对象,是原型链的最顶端,她的隐式原型属性值为null

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值