依次列举从基本实现到最佳方案,想看最佳方案可直接跳到页面末尾
组合继承
function Animal() {
this.type = 'run';
this.classify = [1,2,1];
this.say = function() {
console.log(this.type);
}
}
function Dog() {
Animal.call(this);
}
var dog = new Dog();
dog instanceof Animal; // false,Dog只获得了Animal的属性和方案,但在原型上没有继承关系
原型继承
function Animal() {
this.type = 'run';
this.classify = [1,2,1];
this.say = function() {
console.log(this.type);
}
}
function Dog() {}
Dog.prototype = new Animal;
var dog1 = new Dog();
var dog2 = new Dog();
dog1.classify.push(3);
console.log(dog2.classify); //[1,2,1,3]
dog1.constructor; // Animal
原型继承带来的问题:
- 多个实例对象指向同一个原型对象,原型对象的属性和方法共享,引用类型的属性有数据干扰问题
- 实例对象的constroctor被指向了Animal,而不是Dog
组合加原型继承
function Animal() {
this.type = 'run';
this.classify = [1,2,1];
this.say = function() {
console.log(this.type);
}
}
function Dog() {
Animal.call(this);
}
Dog.prototype = new Animal;
问题:
- 实例对象的constroctor被指向了Animal,而不是Dog
- Animal的构造函数被执行了两次,第一次是call,第二次是new
组合加原型继承优化1
function Animal() {
this.type = 'run';
this.classify = [1,2,1];
this.say = function() {
console.log(this.type);
}
}
function Dog() {
Animal.call(this);
}
Dog.prototype = Animal.prototype;
问题:实例对象的constroctor被指向了Animal,而不是Dog,此时Animal的构造函数只执行一次
组合加原型继承优化2
function Animal() {
this.type = 'run';
this.classify = [1,2,1];
this.say = function() {
console.log(this.type);
}
}
function Dog() {
Animal.call(this);
}
Dog.prototype = Object.create(Animal.prototype);
// Object.create(o),如果o是一个字面量对象或实例对象,那么相当于是实现了对象的浅拷贝
Dog.prototype.constructor = Dog;
这是最佳方案
Object.create时发生了什么?
Object.create()方法创建一个新对象,并使用现有的对象来提供新创建的对象的proto,关键代码如下
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
Object.create(o),如果o是一个构造函数,则采用这种方法来创建对像没有意义
Object.create(o),如果o是一个字面量对象或实例对象,那么相当于是实现了对象的浅拷贝