原型继承

第一步:学会创建对象

  • 工厂模式
function Dog(name, variety) {
    return {
        name: name,
        variety: variety
    };
}
var dog1 = Dog('二牛', '牛头梗');
var dog2 = Dog('二狗', '哈士奇');
  • 构造函数模式
function Dog(name, variety) {
    this.name = name;
    this.variety = variety;
}
var dog1 = new Dog('二牛', '牛头梗');
var dog2 = new Dog('二狗', '哈士奇');
console.log(dog1.name); // 二牛
console.log(dog2.name); // 二狗

与上一个相比没有return语句,直接将属性和方法赋给了this对象
问题:每个方法都要在每个实例上重新创建一遍,所以每一个实例所包含的同名函数是不相等的,如下所示:

print(dog1.bark() === dog2.bark()); // false
  • 原型模式
function Dog(name, variety) {
    this.name = name;
    this.variety = variety;
}
Dog.prototype.type = '犬科';
Dog.prototype.bark = function() {
    console.log('汪汪汪');
}
var dog1 = new Dog('二牛', '牛头梗');
var dog2 = new Dog('二狗', '哈士奇');
console.log(dog1.type); // 犬科
dog1.bark(); // 汪汪汪
print(dog2.type); // 犬科
dog2.bark(); // 汪汪汪
console.log(dog1.bark() === dog2.bark()); // true

Dog 构造函数都有一个prototype属性,指向函数原型对象Dog prototypeDog prototype里面有一个constructor属性,指向Dog,实例dog1,dog2指向Dog prototype,实例内部包含一个指针[[prototype]]表示指向构造函数的原型对象

原型继承_第1张图片

原型链的形成

  • 构造函数,原型,实例之间的关系:
    每个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针,而实例由 new 一个构造函数而生成,包含一个指向原型对象的指针。
原型继承_第2张图片
  • 原型链
    让原型对象的指向为另一个类型的实例,在下图中将SubType的原型对象 SubType Prototype指向了SuperType Prototype构成原型链
原型继承_第3张图片

继承

主要依靠原型链来实现继承

  • 原型继承
function Animal() {
    this.feeling = 'happy';
}
function Dog(name, variety) {
    this.name = name;
    this.variety = variety;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
var dog = new Dog('二狗', '哈士奇');
console.log(dog.feeling); // happy

问题:实例对象共享

function Animal() {
    this.colors = ['red', 'green', 'blue'];
}
function Dog() {
}
// 继承Animal
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
var dog1 = new Dog();
dog1.colors.push('black');
console.log(dog1.colors); // red,green,blue,black
var dog2 = new Dog();
console.log(dog2.colors); // red,green,blue,black
  • 构造函数继承
function Animal() {
    this.feeling = 'happy';
}
function Dog(name, variety) {
    Animal.apply(this, arguments);
    this.name = name;
    this.variety = variety;
}
var dog = new Dog('二狗', '哈士奇');
console.log(dog.feeling); // happy

使用apply或者call方法改变构造函数作用域,将父函数的构造函数绑定到子对象上
问题:方法都在构造函数中定义,函数的复用不存在

  • 构造函数+原型继承
function Animal(name) {
    this.name = name;
    this.colors = ['red', 'green', 'blue'];
}
Animal.prototype.sayName = function() {
    console.log(this.name);
};
function Dog(name, age) {
    // 继承属性
    Animal.call(this, name);
    this.age = age;
}
// 继承方法
Dog.prototype = new Animal();
Dog.prototype.sayAge = function() {
    console.log(this.age);
}
//实例一
var dog1 = new Dog('二狗', 1);
dog1.colors.push('black');
console.log(dog1.colors); // red,green,blue,black
dog1.sayName(); // 二狗
dog1.sayAge(); // 1
//实例二
var dog2 = new Dog('二牛', 2);
console.log(dog2.colors); // red,green,blue
dog2.sayName(); // 二牛
dog2.sayAge(); // 2

参考:http://www.alloyteam.com/2015/06/javascript-shu-ju-jie-gou-he-suan-fa-jian-shu-qian-yan/

你可能感兴趣的:(原型继承)