原型链

通过原型链继承:Child.prototype = new Father(); // Child.prototype.__proto__ === Father.prototype

  • 缺点:
    • 原型链中的引用类型会被所有实例共享
    • 无法向父级构造函数传参 ```javascript // Father.proto === Function.prototype // Father.prototype.proto === Object.prototype function Father(){ } Father.prototype.name = “baba”;

Child.prototype = new Father(); // Child.prototype.proto === Father.prototype function Child(){ }
var child = new Child(); console.log(child.name); // “baba”

  1. <a name="tGYtP"></a>
  2. ### 借用构造函数
  3. 在子构造函数中通过 call()、apply() 调用父级造函数,可以向父级构造函数传参<br />缺点:每个实例都创建了共有属性的副本,破坏了代码的复用性,浪费空间
  4. ```javascript
  5. function Father(name) {
  6. this.name = name;
  7. }
  8. function Child(name) {
  9. Father.call(this, name);
  10. }
  11. var child1 = new Child("baba");
  12. var child2 = new Child("mama");
  13. console.log(child1.name); // "baba"
  14. console.log(child2.name); // "mama"
  15. child2.name = "me"
  16. console.log(child1.name); // "baba"
  17. console.log(child2.name); // "me"

组合继承

原型链 + 借用构造函数,共享属性用原型链继承,非共享属性借用父级构造函数
缺点:需要调用两次父级构造函数,耗内存

  1. function Father(name) {
  2. this.name = name;
  3. }
  4. Father.prototype.getName = function() {
  5. console.log(this.name); // 共享属性通过原型链继承
  6. }
  7. function Child(name) {
  8. Father.call(this, name); // 非共享属性借用父级构造函数
  9. }
  10. Child.prototype = new Father(); // 与寄生组合继承不同之处
  11. Child.prototype.constructor = Child; // Child.prototype.__proto__ === Father.prototype
  12. var child1 = new Child("baba");
  13. var child2 = new Child("mama");
  14. child1.getName(); // "baba"
  15. child2.getName(); // "mama"
  16. child2.name = "me";
  17. child1.getName(); // "baba"
  18. child2.getName(); "me"

原型式继承

  1. // 以 obj 作为原型构建对象
  2. function creatObject(obj) {
  3. function F(){};
  4. F.prototype = obj;
  5. return new F();
  6. }
  7. var parent = {
  8. name: "baba"
  9. }
  10. var child = creatObject(parent);
  11. console.log(child.name); // "baba"

该方法类似通过 Object.create() 创建对象

  1. // 创建对象:Object.create(原型)
  2. var person = Object.create(Person.prototype);
  3. var obj = Object.create(null); //创建没有原型的对

寄生继承

  1. function object(obj) {
  2. var clone = Object.create(obj);
  3. clone.sayHi = function(){
  4. console.log("Hi " + this.name);
  5. }
  6. return clone;
  7. }
  8. var parent = {
  9. name: "baba"
  10. }
  11. var child1 = object(parent);
  12. var child2 = object(parent);
  13. console.log(child1.sayHi === child2.sayHi); // false

寄生组合式继承

组合继承改进版,不需要调用两次父级构造函数

  1. function Parent(name) {
  2. this.name = name;
  3. }
  4. Parent.prototype.getName = function() {
  5. console.log(this.name);
  6. }
  7. function Child(name) {
  8. Parent.call(this, name);
  9. }
  10. function inheritPrototype(Parent, Child) {
  11. Child.prototype = Object.create(Parent.prototype); // 与组合继承不同之处
  12. Child.prototype.constructor = Child;
  13. }
  14. inheritPrototype(Parent, Child);
  15. var child = new Child('baba');
  16. child.getName(); // "baba"

圣杯模式

  1. function inherit(Target, Origin) {
  2. function F() {};
  3. F.prototype = Origin.prototype;
  4. Target.prototype = new F();
  5. Target.prototype.constructor = Target;
  6. Target.prototype.uber = Origin.prototype; // 记录继承原型
  7. }
  8. var inherit = (function() {
  9. function F() {};
  10. return function(Target, Origin) {
  11. F.prototype = Origin.prototype;
  12. Terget.prototype = new F();
  13. Terget.prototype.constructor = Target;
  14. Target.prototype.uber = Origin.prototype;
  15. }
  16. }());

Class 继承

ES6 extends 继承,与 java 类似

  1. class Parent{
  2. constructor(name){
  3. this.name = name;
  4. }
  5. getName(){
  6. console.log(this.name);
  7. }
  8. }
  9. class Child extends Parent{
  10. constructor(name, age){
  11. super(name);
  12. this.age = age;
  13. }
  14. getAge(){
  15. console.log(this.age);
  16. }
  17. }
  18. let child = new Child("baba", 18);
  19. child.getName(); // "baba"
  20. child.getAge(); // 18