1.什么继承?
继承就是某个对象可以访问另一个对象的属性和方法,我们认为他们之间存在继承关系。
举例:
function Chinese(){}
var jack=new Chinese();
//jack可以访问到自身的属性,还可以访问到Chinese.prototype对象中的属性和方法,
//--->我们说jack继承自Chinese.prototype
//--->jack.__proto__===Chinese.prototype
2.继承主流的实现方式:
1.原型式继承
a.扩展原型对象
function Person(){}
//一个函数创建好之后,就会又一个默认的原型对象,需要给这个对象添加属性、方法,我们把这样的方式称之为扩展原型对象实现继承
Person.prototype.run=function(){
console.log("run");
};
var p1=new Person();
console.log(p1.constructor);//Person
//p1
//p1.__proto__--->Person.prototype
console.log(p1.run);
//有时候我们需要给原型对象中扩展多个属性和方法,如果使用扩展原型对象来实现,出现一些重复的代码,我们思考能不能把这些重复封装起来,解决方案:替换原型对象实现继承
Person.prototype.run1=function(){
console.log("run");
};
Person.prototype.run2=function(){
console.log("run");
};
Person.prototype.run3=function(){
console.log("run");
};
Person.prototype.run4=function(){
console.log("run");
};
Person.prototype.run5=function(){
console.log("run");
};
b.替换原型对象
function Person(){}
//一个函数创建好之后,就会又一个默认的原型对象,需要给这个对象添加属性、方法,我们把这样的方式称之为扩展原型对象实现继承
//替换原型对象
Person.prototype={
constructor:Person,
r1:function(){},
r2:function(){},
r3:function(){}
};
var p1=new Person();
console.log(p1.r1);//p1.__prpto__:Person.prototype
2.混入继承(拷贝继承)
function foo(name,age,gender,height,width,language,color){}
foo("zhangsan",20,"男",180,180,"中文","黄色");
function foo2(obj){
this.name=obj.name;
this.age=obj.age;
this.gender=obj.gender;
this.height=obj.height;
this.language=obj.language;
this.width=obj.width;
this.color=obj.color;
//上面的代码又产生了很多的重复的字符,就希望有某种方式可以减少重复
//解决方案:混入继承:for...in循环
for (var key in obj) {//key保存了obj中每一个属性的名称:字符串的值
//获取指定属性的值:
this[key]=obj[key];//举例:this["name"]=obj["name"]
}
}
foo2({
name:"zhagnsan",age:18,
gender:"男",height:180,width:200,language:"英语",
color:"白色"
});
/**
* 将某个对象中的属性分别拷贝到另一个对象中
* 把提供数据的对象称之为数据源对象(source object)
* 把接收数据的对象称之为目标对象(target object)
*/
function mixin(target,source){
for (var key in source) {
//将source中的指定的属性拷贝到target中-->给target添加同名属性
target[key]=source[key];
}
//告诉用户拷贝的结果:
return target;
}
var o1={name:"zhagnsan",age:25,gender:"男"};
var o2={};
console.log(mixin(o2,o1));
var o3={name:"zhagnsan",age:25,gender:"男"};
var o4={length:10,gender:"女"};
console.log(mixin(o4,o3));//o4-->{name:"zhangsan",age:25,gender:"男",length:10}
3.原型式继承(经典继承)
//原型式继承:经典继承-->由道格拉斯在蝴蝶书(javascript语言精粹)中提出
function mixin(target,source){
for (var key in source) {
//将source中的指定的属性拷贝到target中-->给target添加同名属性
target[key]=source[key];
}
//告诉用户拷贝的结果:
return target;
}
var o3={name:"zhagnsan",age:25,gender:"男"};
var o4={length:10,gender:"女"};
//希望o4中可以访问到length/gender:"女"/-->name/age
//实现思路:让o3和o4之间产生某个联系(继承关系)
// -->o4继承自o3
// -->o4.__proto__==o3 -->o4就不仅可以访问到自己的属性,也可以正常访问到o3的一些属性
//不能直接使用:o4.__proto__==o3,因为__proto__属性是非标准属性,具有浏览器兼容性问题
//曲线救国的方式:
//想到之前:function Person(){} var p1=new Person(); p1.__proto__===Person.prototype
//为了实现上面的关系,需要进行相关的转换,也就是通过某个构造函数创建一个实例o4,执行构造函数的原型指向o3
function F(){}
F.prototype=o3;//让F的实例都可以访问到o3中的属性
var o5=new F();//o5.__proto__===o3
o5.length=10;
o5.gender="女";
console.log(o5.length);//自己的length
console.log(o5.gender);//自己的gender
console.log(o5.name);//自己没有,访问o3的name属性
//总结:
//原型式继承的功能:创建一个新的对象,让新的对象可以继承自指定的对象,从而这个新的对象既可以访问到自己的属性,也可以访问到指定的对象的属性
//现代浏览器中:Object.create()实现了原型式继承(经典继承)
//ES5(js语言规范的第五个版本)——Object.create()--->IE9以下不支持
//var o6=Object.create(o3);//o6继承自o3
//如果希望写出一段代码,实现原型式继承,让它可以兼容所有的浏览器
//执行过程:首先判断浏览器是否存在这个方法,如果不存在,这个浏览器自己没有实现经典继承,就帮他实现
// 如果已经存在,就不需要进行任何操作
//经过上面的处理之后,就实现了可以在任意浏览器版本中,可以调用Object.create()
if(!Object.create){
Object.create=function(parent){
function F(){}
F.prototype=parent;
return new F();
};
}
alert(Object.create.toString());
var o7=Object.create(o3);//o6继承自o3
alert(o7.name);
4.借用构造函数继承
5.寄生继承、寄生组合、组合继承