js中的继承
继承属性
JavaScript对象是一个动态的属性“包”,每个对象都有一个指向一个原型对象的链,当我们访问一个对象的属性时,他不仅会在该对象上搜索,还会搜寻该对象的原型,以及该对象的原型的原型,这样依次向上寻找,直到找到一个名字匹配的属性或者到达原型链的末端(null)
继承的实现方法
先实现一个父级函数
function Person(name, age){
this.name = name || "Person";
this.age = age||'18';
//实例方法
this.say = function(){
console.log(this.name)
}
}
//原型方法
Person.prototype.eat=function(food){
console.log("我是" + this.name + ",我正在吃:" + food)
}
原型继承
实现:将父函数的实例赋值给子函数的原型
//创建子类-学生
function Student(){}
Student.prototype = new Person();
var stu = new Student();
console.log(stu.name);//Person
stu.eat("apple");//我是Person,我正在吃:apple
console.log(stu instanceof Student);//true
console.log(stu instanceof Person);//true
特点:
- 父级函数原型发生变化时,子类都能访问到
- 简单,易于实现
缺点:
- 想要为子类新增属性和方法,必须在完成赋值父函数的实例之后再执行
- 无法实现多继承(继承多个父类)
- 创建子类实例时,无法向父类构造函数传参
- 父级函数原型中所有属性都被所有实例共享
借用构造函数继承
原理:使用call、apply改变父函数内this,指向子函数,用父级构造函数来增强子类实例
function Student(name, grade){
Person.call(this, name);
this.grade = grade;
this.say = function(){
console.log(`我是${this.name},现在${this.grade}年级`)
}
}
var stu = new Student('tom', '3');
console.log(stu.name);//tom
stu.say();//我是tom,现在3年级
console.log(stu instanceof Person);//false
console.log(stu instanceof Student);//true
特点:
- 可以向父级函数中传递参数
- 可以实现多继承
- 解决了1中子类实例共享所有父类原型属性的问题
缺点:
- 只能继承实例属性和方法,不能继承原型属性方法
- 实例只是子类的实例,不是父类的实例
组合继承
原理:结合1和2
function Student(name, grade){
Person.call(this, name);
this.grade = grade;
this.say = function(){
console.log(`我是${this.name},现在${this.grade}年级`)
}
}
Student.prototype = new Person();
var stu = new Student('tom', 3);
stu.say();//我是tom,现在3年级
stu.eat('apple');//我是tom,我正在吃:apple
console.log(stu instanceof Student);//true
console.log(stu instanceof Person);//true
特点:
- 既可以继承实例方法和属性,也可以继承原型方法和属性
- 既是子类的实例,也是父类的实例
缺点:
- 调用了两次父类构造函数,生成了两份父类实例属性,父类实例属性和方法也在子类原型中
寄生方式继承
寄生组合继承
原理:通过寄生方式,去掉父类实例属性,这样就不会初始化两次父类的实例方法/属性,避免了组合方式继承的缺点
function Super(){};
Super.prototype = Person.prototype;
function Student(name, grade){
Person.call(this, name);
this.grade = grade;
this.say = function(){
console.log(`我是${this.name},现在${this.grade}年级`)
}
}
Student.prototype = new Super();
var stu = new Student('tom', 3);
stu.say();//我是tom,现在3年级
stu.eat('apple');//我是tom,我正在吃:apple
console.log(stu instanceof Student);//true
console.log(stu instanceof Person);//true