继承的方式
一.原型链继承
将构造函数的原型设置为另一个构造函数的实例对象,这样就可以继承另一个原型对象的所有属性和方法,可以继续往上,最终形成原型链。
核心: 将父类的实例作为子类的原型
注:
instanceof运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回值为 true 或 false
原型链的追加:
先继承父类,才能追加元素
function Parent(){
this.name=null;
this.eat=function(){
return "吃"
};
this.sleep=function(){
return "睡觉"
}
}
function Son() {
this.type = "孩子";
}
// 原型链继承
Son.prototype =new Parent ();
//原型链的追加
Son.prototype.color="red";
var son=new Son();
console.log(son);
console.log( typeof son); //object
console.log(son instanceof Son); //true
console.log(son instanceof Parent);//true
优点:
1.非常纯粹的继承关系,实例是子类的实例,也是父类的实例
2.父类新增原型方法/原型属性,子类都能访问到
3.简单,易于实现
缺点:
1.要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中无法实现多继承
2.创建子类实例时,无法向父类构造函数传参
二、构造继承
为了解决原型中包含引用类型值的问题,开始使用借用构造函数,也叫伪造对象或经典继承.
使用call
或apply
方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行。
call apply 对象指针的替换
区别: 传递的参数的方式不一样
call 有多个参数
apply 有两个参数
apply(this , [ 值一,值二] )
call(this , 值一,值二,…)
核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
注:提及一下arguments的用法
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。例如,如果一个函数传递了三个参数,你可以以如下方式引用他们:
arguments[0]
arguments[1]
arguments[2]
arguments对象不是一个 Array 。它类似于Array,但除了length属性和索引元素之外没有任何Array属性。
function f1(){
this.name=arguments [0];
this.sex=arguments [1];
this.eat=function(){
return this.name+"在吃饭"
};
}
function f2(){
this.habby=arguments [0];
this.sleep=function(){
return "睡觉"
};
}
function f3(name,sex,habby){
f1.apply(this,[name,sex]);
f2.call(this,habby);
}
var f33 =new f3("李凡","女","煮饭");
console.log(f33);
console.log(f33.eat());
console.log(f33 instanceof f1); //false
console.log(f33 instanceof f3); //true
特点:
1.创建子类实例时,可以向父类传递参数
2.可以实现多继承(call多个父类对象)
缺点:
1.实例并不是父类的实例,只是子类的实例
2.只能继承父类的实例属性和方法,不能继承原型属性/方法
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
组合继承=原型+构造
也叫伪经典继承,将原型链和借用构造函数的技术组合到一块。使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承
function fu(){
this.name=arguments [0];
this.sex="女";
this.habby=function(){
return "看书"
}
}
function Zi(name){
fu.call(this,name);
}
//先继承父级才能追加元素
Zi.prototype=new fu();
var zi =new Zi("fan");
/*Zi.prototype.eat =function(){
return "吃饭"
}*/
console.log(zi); //Zi {name: "fan", sex: "女", habby: ƒ}
console.log(zi instanceof Zi);
console.log(zi instanceof fu);
特点:
弥补了构造继承的缺陷
缺点:
生成了两个实例,消耗内存;
四.实例继承
function old(){
this.name="mm";
this.sex="女";
this.eat=function(){
return "面皮"
}
}
function yonger(){
var y=new old();
return y;
}
var yong=new yonger();
console.log(yong); // old {name: "mm", sex: "女", eat: ƒ}
console.log(yong instanceof old); //true
console.log(yong instanceof yonger);//false
特点:
不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
实例是父类的实例,不是子类的实例
不支持多继承