JS继承方式
- 类式继承(核心思想是将父类的实例对象赋值给子类的原型对象)
- 构造函数式继承(核心思想:调用Object.call()方法,将子类的this绑定到父类上)
- 组合式继承(在子类构造函数中通过call方法执行父类,用以继承父类的共有属性,在子类原型上实例化父类用以继承父类的原型方法)
- 寄生式继承
1.1 类式继承
//声明父类
function SupperClass(){
this.name = '张三'
}
//声明子类
function SubClass(){}
//将父类的原型赋值给子类的原型对象
SubClass.prototype = new SupperClass()
//实例化子类
var f = new SubClass();
console.log(f.name)
1.2 构造函数式继承
//声明父类
function SupperClass(sex){
this.name = '张三';
this.sex = sex
}
//声明子类
function SubClass(){
SupperClass.call(this)
}
var person = new SubClass()
console.log(person.name)
1.3 组合式继承
//声明父类
function SupperClass(sex){
//父类共有属性
this.name = '张三';
this.sex = sex
}
//定义父类原型方法
SupperClass.prototype.getName = function(){
return this.name
}
//声明子类
function SubClass(){
//在子类中执行父类
SupperClass.call(this)
}
SubClass.prototype = new SupperClass();
var person = new SubClass();
var person2 = new SubClass();
console.log(person.name) //张三
person.name = '王八'
console.log(person.getName()) //王八
console.log(person2.getName())//张三
1.4 寄生式继承
//声明原型继承函数
function inhertObj(o){
//声明一个过渡函数
function F(){}
//过渡函数对象的原型继承自父对象
F.prototype = o;
//返回过渡对象的实例
return new F()
}
/*然而这种方式会子类实例会污染父类的引用型对象
如:*/
var person = {
names:['王八','二狗子'],
sex:'女'
}
var newPerson = inhertObj(person);
newPerson.sex = '男';
newPerson.names.push('汉奸');
var newPerson2 = inhertObj(person);
newPerson2.sex = '不男不女';
newPerson2.names.push('小鬼子');
//父类的值类型的属性会被复制,引用型会被共享(污染)
console.log(newPerson.sex);//男
console.log(newPerson.names);//["王八", "二狗子", "汉奸", "小鬼子"]
console.log(newPerson2.sex);//"不男不女"
console.log(newPerson2.names);//["王八", "二狗子", "汉奸", "小鬼子"]
<!--由于person.names被污染了,所以继承了它的子类也没有得到预期的结果-->
console.log(person.sex);//女
console.log(person.names);//["王八", "二狗子", "汉奸", "小鬼子"]
//寄生式继承
//声明基对象
var person = {
names:['王八','二狗子'],
sex:'女'
}
function creatPerson(obj){
//通过原型继承方式创建新对象
var o = new inhertObj(obj);
//拓展新对象
o.getNames = function(){
console.log(o.names)
}
return o;
}
//寄生组合式继承
/*
寄生式继承 继承原型
传递参数 subClass 子类
传递参数 superClass 父类
*/
function inhertPrototype(subClass,superClass){
//复制父类的原型用一个变量保存
var p = inhertObj(superClass.prototype);
//将复制对象的constructor重新指向subClass子类
//修正因重写子类原型导致子类的constructor属性被更改
p.constructor = subClass;
//再将复制对象(父类对象的副本)赋值给子类的原型
subClass.prototype = p;
}
/*
注意:由于子类原型是父类原型的一个引用对象,所以给子类添加新方法时只能通过点语法一个一个添加,而不能直接修改子类的原型对象否则将会覆盖从父类原型继承的对象。
*/
补充:继承单对象的extend方法
//对象的浅复制
var extend = function(targetObj,sourceObj){
//遍历源对象中的属性(不包含引用类型和描述符属性,如:writable,enumerable)并将它赋值给目标对象
for(var attr in sourceObj){
targetObj[attr] = sourceObj[attr]
}
return targetObj;
}