前置知识
有3个封装的方法可以实现改变this指向,bind(),call(),apply().
call():
function Father(){
console.log(this.name)
}
function Son(){
this.name ='张三'
Father.call(this)
}
call()和apply()功能差不多,只是apply()传递的参数除this之外另外的一个用数组包含
bind(): 也是改变this指向,意为绑定,call和apply本身就有调用立即执行的意思,但bind不会立刻执行,它只是绑定,返回一个绑定的函数
function Father(){
console.log(this.name)
}
function Son(){
this.name ='张三'
var son = Father.bind(this)
son()
}
Son()
一,通过call, apply改变this指向继承
function Person(name){
this.name =name
console.log(this.name,this.age)
}
function Student(name,age){
this.age = age
Person.call(this,name)
}
Student('张三',18)
每次继承都会调用父类,本质上就是改变this指向,调用父类,导致多执行父类上的代码,
因此存在缺点:
因为只是执行了父类上表面的代码,导致父类原型上的方法与属性没有得到继承。
二,原型链继承
想要父类原型上的方法实现继承,考虑可以将子类作为父类的一个实例对象,这样子类就可以查找到父类的原型
Person.prototype.age =18;
function Person(){
this.sayHello=function(){
console.log('你好!')
}
}
function Student(){
}
Student.prototype=new Person();
Student.prototype.constructor =Student;
var student =new Student();
console.log(student.age)
student.sayHello()
缺点,无法像call那样传递参数
function Person(name){
this.name =name
}
无法实现,student接收不到,这种方法无法传递参数
三,组合方法
用call传递参数,原型链实现原型上的继承
Person.prototype.age =18;
function Person(name){
this.name=name
}
function Student(name){
Person.call(this,name)
}
Student.prototype=new Person();
Student.prototype.constructor =Student;
var student =new Student('张三');
console.log(student.name,student.age)
缺点:
父类中的实例属性和方法既存在于子类的实例中,又存在于子类的原型中,不过仅是内存占用,因此,在使用子类创建实例对象时,其原型中会存在两份相同的属性和方法 。