js 继承

33 阅读2分钟

原型链继承

function Parent1() {
    this.name = 'parent1';
    this.play = [1, 2, 3]
}
function Child1() {
    this.type = 'child2';
}
Child1.prototype = new Parent1();
console.log(new Child1());

////////////
var s1 = new Child1();
var s2 = new Child1();
s1.play.push(4);
console.log(s1.play);
console.log(s2.play);
//当我修改了s1的play属性的时候,s2的play属性也跟着变了。

构造函数继承(借助 call)

function Parent1(){
    this.name = 'parent1';
}

Parent1.prototype.getName = function () {
    return this.name;
}

function Child1(){
    Parent1.call(this);
    this.type = 'child1'
}

let child = new Child1();
console.log(child);  // 没问题
console.log(child.getName());  // 会报错

//只能继承父类的实例属性和方法,不能继承原型属性或者方法。

组合继承(原型链继承、构造函数继承)

// 创建父类构造函数
function Animal(name) {
  this.name = name;
}

// 父类方法
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}

// 创建子类构造函数
function Dog(name, breed) {
  Animal.call(this, name); // 调用父类构造函数,绑定当前子类的this到父类构造函数上
  this.breed = breed; // 子类特有的属性
}

// 将父类的实例赋值给子类构造函数的原型
//Dog.prototype = Object.create(Animal.prototype);

// 父类构造函数的实例
let animal = new Animal()
// 设为子类的原型对象
Dog.prototype = animal
// 修复constructor指针
Dog.prototype.constructor = Dog

// 子类特有的方法
Dog.prototype.bark = function() {
  console.log('Woof!');
}

// 创建子类实例
var myDog = new Dog('Max', 'Labrador');

// 调用继承的父类方法
myDog.sayName(); // 输出 'My name is Max'

// 调用子类特有的方法
myDog.bark(); // 输出 'Woof!'


////////////////////////
// Animal是父类构造函数,Dog是子类构造函数,Dog通过调用Animal构造函数实现继承父类的属性。然后将Animal的实例赋值给Dog的原型,使得Dog可以继承父类的方法。最后可以通过创建Dog的实例来调用继承的父类方法和子类特有的方法。
// 但是这样的继承存在一个问题,Animal 构造了两次。

寄生式继承

let parent5 = {
    name: "parent5",
    friends: ["p1", "p2", "p3"],
    getName: function() {
        return this.name;
    }
};

function clone(original) {
    let clone = Object.create(original);
    clone.getFriends = function() {
        return this.friends;
    };
    return clone;
}

let person5 = clone(parent5);

console.log(person5.getName());
console.log(person5.getFriends());

// 缺点:没用到原型,无法复

原型式继承

function Parent(name) {
  this.name = name;
}
function content(obj){
  function F(){};
  F.prototype = obj;
  return new F();
}


//es5之后
const obj = {a:1};
const test = Object.create(obj);


var sup = new Person();
var sup1 = content(sup);
console.log(sup1.name);

// 所有实例都会继承原型上的属性。

完美继承(寄生组合)

function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
}

function Child(name, age) {
  // 继承属性
  Parent.call(this, name); // 组合式继承
  this.age = age;
}

// 继承方法
Child.prototype = Object.create(Parent.prototype); // 寄生继承


Child.prototype.sayAge = function() {
  console.log(`I am ${this.age} years old`);
}


/////////////////////////////////
// 通过使用call和apply方法组合继承继承属性,寄生继承继承方法,我们成功实现了Child构造函数继承了Parent构造函数的属性和方法