什么是混合继承?
原型链继承和借用构造函数继承。这两种模式都存在各自的缺点,所以组合继承是将二者结合到一起,从而发挥二者之长。即在继承过程中,既可以保证每个实例都有它自己的属性,又能做到对一些属性和方法的复用.
案例
function Person(name) {
this.name = name;
}
Person.prototype.saySex = function() {
console.log("性别分为男女")
}
Person.prototype.sayName = function() {
console.log(this.name)
}
function Animal(name) {
//通过call 使Person的this指向Animal的this
Person.call(this,name);
}
Animal.prototype = Object.create(Person.prototype)
//因为 动物性别不是男女 所以我们需要改写 saySex
Animal.prototype.saySex = function() {
console.log("性别分为公母")
}
var dog = new Animal("狗")
dog.sayName()
dog.saySex() 复制代码
结果如下:
总结:
为什么 Animal.prototype = Object.create(Person.prototype)
而不是 Animal.prototype = new Person()
Object.create
function Person(name) {
this.name = name;
}
Person.prototype.saySex = function() {
console.log("男")
}
var person1 = Object.create(Person);
console.log(person1.saySex) // undefined
console.log(person1.name) // "Person"复制代码
为什么会出现这样的结果?
首先看看 Object.create
到底干了啥?
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};复制代码
通过代码我们知道
1)因为Object.create内部的新对象是new F()创建的,跟Person构造函数没有关系,所以不能访问到Person中的属性
2)调用person1.saySex 时首先判断person1对象有没有相应的方法,如果没有,则查找person1的原型链上有没有该方法,person1的原型属性是Person构造函数(可以通过person1.__proto__来证明), 构造函数没有saySex方法,自然也就是undefined了。
3) return new F()后F被销毁,Object.create创建对象是创建一个拥有指定原型和若干个指定属性的对象,也就是说可以任意指定原型,甚至是null。所以在上述中像o.prototype添加属性不被继承
如果换成 Object.create(Person.prototype)
; 会是什么情况呢?
function Person(name) {
this.name = name;
}
Person.prototype.saySex = function() {
console.log("男")
}
var person1 = Object.create(Person.prototype);
console.log(person1.saySex)
console.log(person1.name) 复制代码
输出结果如下:
new方法创建对象
new Object()方法的实质是,使用引用类型Object的构造函数创建了一个新的实例,这个实例拥有Object默认的方法如toString、toLocaleString等。经历了以下四个步骤:
1) 创建一个新对象;
2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
3) 执行构造函数中的代码(为这个新对象添加属性) ;
4) 返回新对象。
当我们执行:
function Person() {
}
var person1 = new Person();
复制代码
实际上是按照如下过程执行的:
var person1 = {};
person1.__proto__ = Person.prototype;
Person.call(person1);复制代码
其实在new 的过程中 我们执行了构造函数的方法,而在create 过程中我们并没有执行构造函数的方法
Object.create()兼容性写法
function create(obj) {
if (Object.prototype.toString.call(obj) !== '[object Object]') {
throw new Error('need an object type');
}
function CreatePrototype() {
}
CreatePrototype.prototype = obj;
return new CreatePrototype();
}复制代码
使用:
Animal.prototype = create(Person.prototype)