l 继承的引入
1. 三个this的区别
console.log(this);//window
function animal(){
console.log(this); //this 代表当前实例化的对象animal
}
var cat=new animal(); //实例化对象
实例化一个对象实例化之后可直接通过对象.属性或方法调用
object.οnclick=function(){
console.log(this);// this当前事件的执行对象object
}
l 继承的前提
1. 先定义一个父类
2. 再定义一个子类
3. 然后再通过不同的方法实例化子类对象
例如
//声明一个父类
function Animal(name){
this.name=name; //设置属性
this.eat=function(){ //设置实例方法
return this.name+"正在吃饭"
}
}
Animal.prototype.sex="公" //设置原型属性
Animal.prototype.sleep=function (){
return this.name+"正在睡觉!"; //设置原型方法
}
//声明一个子类在子类外面实例化
cat=function(){
}
//实例化子类
CAT=new cat("猫") //注意带参
l 实现继承的四种不同方法
1、原型链继承
核心: 将父类的实例作为子类的原型
实现方式,在子类外面原型父类,再实例化子类
特点:
非常纯粹的继承关系,实例是子类的实例,也是父类的实例
父类新增原型方法/原型属性,子类都能访问到
简单,易于实现
缺点:
要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中无法实现多继承
创建子类实例时,无法向父类构造函数传参
示例代码如下
//声明一个父类
function Animal(name){
//设置属性
this.name=name;
//设置实例方法
this.eat=function(){
return this.name+"正在吃饭"
}
}
//设置原型属性
Animal.prototype.sex="公"
//设置原型方法
Animal.prototype.sleep=function (){
return this.name+"正在睡觉!";
}
//声明一个子类在子类外面实例化
cat=function(){
}
//实例化对象
//原型链继承,直接继承的是父类整体,既包括方法,也包括属性,跟call不一样无法实现多继承
//即将父类的实例作为子类的原型,protoptype是原型
cat.prototype=new Animal("猫")//只有一个参数,原型属性直接.调用即可
//为子类新增属性和方法,必须要在new Animal()这样的语句之后执行即,并且给子类添加的属性或方法父类没有影响
cat.prototype.type="犬类"
cat.prototype.play=function(){
return this.name+"正在玩耍"
}
CAT=new cat("猫")
//继承之后可直接通过.属性或者方法获取
console.log(Animal.type)
console.log(CAT.name)
console.log(CAT.eat())
console.log(CAT.sex)
console.log(CAT.sleep())
console.log(CAT.type)
console.log(CAT.play())
//说明实例化的对象既是子类cat的实例,也是父类Animal的实例
console.log(CAT instanceof Animal); //true
console.log(CAT instanceof cat); //true
2、构造继承
核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
实现方式,在子类里面用call或apply子类外,实例化子类
特点:
创建子类实例时,可以向父类传递参数
可以实现多继承(call多个父类对象)
缺点:
实例并不是父类的实例,只是子类的实例
只能继承父类的实例属性和方法,不能继承原型属性/方法
无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
示例代码如下
构造继承等于是复制父类的实例属性给子类(没用到原型),在创建的子类里面进行实例化
两种不同替换对象方法call apply用法一致传递的参数不一样apply(object,[]/arguments) call(object,x1,x2,x3....)
为了方便创建一个相同的父类Animal
//再创建一个父类,验证多继承
function Type(type){
this.type=type;
this.bite=function (){
return "咬人!"
}
}
//声明一个子类在子类里面进行替换和实例化
function dog(name,age,type){ //type参数验证多继承
//方法1可以将子的参数直接传给父类即创建子类实例时,可以向父类传递参数,有两个参数
Animal.call(this,name) //this指的是当前的子类即将子类的值替换成父类或将父类的值复制给子类
方法2,也可以直接先继承然后再重新赋值只有一个参数this
Animal.call(this)
this.name=name
this.age=age
//对于多个参数
//Animal.call(this,name,age)
//或者用apply用法与call一样,只是第二个参数形式不一样
Animal.apply(this,arguments)
//方法2
//Animal.apply(this,[name,age])
Type.apply(this,[type]) //call或apply多个对象
//实现多继承,但是一个参数不能自用argument即不能跟第一个call对象相同
}
dog.prototype.type="犬类" //给子类新加属性方法
dog.prototype.play=function(){
return this.name+"正在玩耍"
}
var DOG=new dog("狗",21,"犬类") //子类外实例化子类
console.log(Animal.type)//undefined给子类新加的属性并没有影响父类
console.log(DOG.play())
console.log(DOG.name)
console.log(DOG.age)
//但注意构造继承只能继承父类的实例属性和方法,不能继承原型属性/方法
/!* console.log(DOG.sex) //找不到
console.log(DOG.sleep()) //找不到*!/
//可以实现多继承
console.log(DOG.type)
console.log(DOG.bite())
//实例并不是父类的实例,只是子类的实例
console.log(DOG instanceof dog); //true
console.log(DOG instanceof Animal); //false
4,组合继承
实现方式,在子类里面用call或apply子类外,先加上原型父类再实例化子类
特点:
弥补了构造继承的缺陷,可以访问父类原型属性和方法
缺点:
生成了两个实例,消耗内存;
示例代码如下
//组合继承即原型链继承和构造继承的组合,优点是可以集成到原型属性和方法,跟构造一样,再子类外面加上原型继承
为了方便创建一个相同的父类Animal
//声明一个子类在子类外面实例化
pig=function(name){
Animal.apply(this,arguments)
}
pig.prototype=new Animal() //子类外原型父类加上之后就变成了组合继承,可以访问原型属性或方法
var PIG=new pig("猪")
console.log(PIG.name)
console.log(PIG.eat())
//本来访问不到,但是再组合加上原型链集成之后就可以访问了
console.log(PIG.sex) //可以访问
console.log(PIG.sleep())
//说明实例化的对象既是子类pig的实例,也是父类Animal的实例
console.log(PIG instanceof Animal); // true
console.log(PIG instanceof pig); // true
4. 实例继承
实现方式,实例化继承 子类里用一个新变量实例化父类对象,返回新变量,子类外实例化子类
特点:
不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
实例是父类的实例,不是子类的实例
不支持多继承
//实例化继承 子类里用一个新变量实例化父类对象,返回新变量,子类外实例化子类
为了方便创建一个相同的父类Animal
//创建子类
function dog(name){
var quan=new Animal() //子类里用一个新变量实例化父类对象,返回新变量,
quan.name="狗"
return quan
}
//var DOG=new dog()//方法1子类外实例化子类 new()
var DOG=dog() //方法2 直接()
console.log(DOG.name)
//说明实例化的对象不是子类dog的实例,但是是父类Animal的实例
console.log(DOG instanceof Animal); // true
console.log(DOG instanceof dog); // false
l Call和apply的扩展使用方法
1.数组的拼接
var a=[1,2,3];
var b=[1,4,5,6,7];
Array.prototype.push.apply(a,b);
console.log(a);相当于
console.log(a.concat(b))
2.求数组中最大,最小值
var c=[1,3,4,5,2,6,7];
console.log( Math.max.apply(null,c));
console.log( Math.min.apply(null,c));