谈到继承我们不可避免的就要说道原型链和prototype,下面让我们用一段代码开始
上述代码中,我们创建了构造函数Animal并用它实例化了一个对象Tom,下面我们就来看一下这段代码形成的原型链。
(1)使用call或apply方法,将父对象的构造函数绑定在子对象上。
(2)使用prototype继承
上述代码将Dog的prototype指向了Animal的实例对象,这会改变constuctor的指向
因此需要手动将Dog的prototype的constuctor属性变回Dog。
(3)直接继承prototype
因为对象的公用属性或方法可以写在对象的prototype对象中,所以我们可以直接让子构造函数的prototype直接指向父构造函数的prototype实现继承。
与前一种继承的方式相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。缺点是 Dog.prototype和Animal.prototype现在指向了同一个对象,那么任何对Dog.prototype的修改,都会反映到Animal.prototype。
需要解决这种冲突,需要通过一层空对象去实现继承。
这里我们给child一个uber属性指向parent的prototype(4)拷贝继承
上面一直都是使用prototype来进行继承,我们也可以换一种思路,纯粹采用"拷贝"方法实现继承。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?
这个函数的作用,就是将父对象的prototype对象中的属性,拷贝给Child对象的prototype对象。
(5)Object.setprototype()
我们来看一下它做了什么
说到这里我们就不得不说一下__proto__(隐式原型)和prototype(显式原型)的区别了。
要讲解原型与原型链,首先,我们要了解两个基本概念——__proto__和prototype。
(1) prototype(函数的原型对象):函数才有prototype,而且所有函数必有prototype。prototype是一个对象,指向了当前构造函数的引用地址。
(2) __proto__(对象的原型):对象才有__proto__,而且所有对象必有__proto__属性(这里的对象除了我们理解的狭义对象,也包括了函数、数组等对象)。当用构造函数实例化(new)一个对象时,会将新对象的__proto__属性,指上构造函数的prototype。
网友评论