继承的使用场景
想要开车,自己没有怎么办?自己造、自己存钱买都太慢了, 继承!爸爸有车,直接拿过来,自己用
想要一个功能,自己没写过怎么办?自己写太慢,继承!别人有代码,直接继承过来,自己用
继承的几种方式
-
原型链继承
优点:简单
缺点:继承方法,不能传参// 1. 原型链继承:不能传参数 function People(name) { this.name= name; this.eat = function () { console.log(this.name + '吃饭'); } } People.prototype.sleep = function () { console.log(this.name + '睡觉'); } function Student(score) { this.score = score; this.study = function () { console.log(this.name + '学习' + this.score + '分'); } } Student.prototype = new People(); Student.prototype.constructor = Student; let s1 = new Student('赵一', 10) console.log(s1); console.log(s1.name);// undefined s1.eat() // undefined吃饭 s1.sleep() // undefined睡觉 s1.study() // undefined学习分 // 测试继承关系 console.log(s1.__proto__.constructor);// Student console.log(s1.__proto__.__proto__.constructor); // People console.log(s1.__proto__.__proto__.__proto__.constructor); // Object console.log(s1.__proto__.__proto__.__proto__.__proto__); // null
-
构造函数继承
优点:解决了方法一的问题
缺点:1.父级原型身上的方法无法继承 2.找不到父级构造者function People(name) { this.name = name; this.eat = function () { console.log(this.name + '吃饭'); } } People.prototype.sleep = function () { console.log(this.name + '睡觉'); } function Student(name, score) { People.call(this, name) this.score = score; this.study = function () { console.log(this.name + '学习' + this.score + '分'); } } let s2 = new Student('钱二', 20) console.log(s2); console.log(s2.name);// 钱二 s2.eat() // 钱二吃饭 // s2.sleep() // 报错 s2.study() // 钱二学习20分 // 测试继承关系 console.log(s2.__proto__.constructor); // Student console.log(s2.__proto__.__proto__.constructor); // Object console.log(s2.__proto__.__proto__.__proto__); // null
-
原型链继承+构造函数继承的组合继承
优点:解决了方法一、方法二的问题
缺点:调用两次父级function People(name) { this.name = name; this.eat = function () { console.log(this.name + '吃饭'); } } People.prototype.sleep = function () { console.log(this.name + '睡觉'); } Student.prototype = new People(); Student.prototype.constructor = Student; function Student(name, score) { People.call(this, name) this.score = score; this.study = function () { console.log(this.name + '学习' + this.score + '分'); } } let s3 = new Student('孙三', 30) console.log(s3); console.log(s3.name);// 孙三 s3.eat() // 孙三吃饭 s3.sleep() // 孙三睡觉 s3.study() // 孙三学习30分 console.log(s3.__proto__.constructor); // Student console.log(s3.__proto__.__proto__.constructor); // People console.log(s3.__proto__.__proto__.__proto__.constructor); // Object console.log(s3.__proto__.__proto__.__proto__.__proto__); // null
-
原型式继承
优点:传入obj对象,生成一个继承obj对象的对象
缺点:缺少了类的概念function People(name) { this.name = name; this.eat = function () { console.log(this.name + '吃饭'); } } People.prototype.sleep = function () { console.log(this.name + '睡觉'); } function Student(name, score) { People.call(this, name) this.score = score; this.study = function () { console.log(this.name + '学习' + this.score + '分'); } } function myObjecCreate(protoObj) { function F() { } F.prototype = protoObj return new F() } Student.prototype = myObjecCreate(People.prototype) // es5 新增了Object.create。优化了方法4的myObjecCreate方法,可以直接替换 // Student.prototype = Object.create(People.prototype) Student.prototype.constructor = Student; let s4 = new Student('李四', 40) console.log(s4); console.log(s4.name);// 李四 s4.eat() // 李四吃饭 s4.sleep() // 李四睡觉 s4.study() // 李四学习40分 console.log(s4.__proto__.constructor); // Student console.log(s4.__proto__.__proto__.constructor); // People console.log(s4.__proto__.__proto__.__proto__.constructor); // Object console.log(s4.__proto__.__proto__.__proto__.__proto__); // null
-
拷贝继承
优点:支持多继承
缺点:1.效率低,不可枚举的属性方法无法拷贝 2.找不到父级构造者function People(name) { this.name = name; this.eat = function () { console.log(this.name + '吃饭'); } } People.prototype.sleep = function () { console.log(this.name + '睡觉'); } function Student(name, score) { let p = new People(name) for (let key in p) { Student.prototype[key] = p[key]; } this.score = score; this.study = function () { console.log(this.name + '学习' + this.score + '分'); } } let s5 = new Student('周五', 50) console.log(s5); console.log(s5.name);// 周五 s5.eat() // 周五吃饭 s5.sleep() // 周五睡觉 s5.study() // 周五学习50分 console.log(s5.__proto__.constructor); // Student console.log(s5.__proto__.__proto__.constructor); // Object console.log(s5.__proto__.__proto__.__proto__); // null
-
es6的class、extends类的继承
优点:简单、类似于java有更强的语义
缺点:无class People{ constructor(name,age){ this.name = name; } eat(){ console.log(this.name + '吃饭'); } sleep = function(){ console.log(this.name + '睡觉'); } } class Student extends People{ constructor(name,score){ super(name) this.score = score; } study(){ console.log(this.name + '学习' + this.score + '分'); } } let s6 = new Student('吴六',60) console.log(s6); console.log(s6.name);// 吴六 s6.eat() // 吴六吃饭 s6.sleep() // 吴六睡觉 s6.study() // 吴六学习60分 console.log(s6.__proto__.constructor); // Student console.log(s6.__proto__.__proto__.constructor); // People console.log(s6.__proto__.__proto__.__proto__.constructor); // Object console.log(s6.__proto__.__proto__.__proto__.__proto__); // null