编程语言
880
继承是让一个对象拥有另一个对象的属性和方法, 主要作用是避免代码的冗余和重复 JavaScript 语言的继承不通过 class,而是通过“原型对象”(prototype)实现 ES6引入了class语法, 基于class的继承将会在下一节讲解
使用继承的优点
function Init (x1, x2) { this.x1 = x1 ; this.x2= x2; this.add = function(){ x1 += x2; }; } var init1 = new Init (0, 1); var init2 = new Init (1, 2);
由于add
方法是生成在每个实例对象上面,所以两个实例就生成了两次。
也就是说,每新建一个实例,就会新建一个add
方法。
问题的解决方法,就是 JavaScript 的原型对象(prototype)。
prototype
继承机制的设计思想: 原型对象的所有属性和方法,都能被实例对象共享。 若属性和方法定义在原型上,所有实例对象就能共享 不仅节省内存,还体现实例之间的联系。
为对象指定原型, 每个函数默认具有prototype
属性,指向一个对象。
function f() {} typeof f.prototype // "object"
对于构造函数来说,生成实例时,该属性会自动成为实例对象的原型。
function Init (x1) { this.x1 = x1 ; } init.prototype.x2 = 3; var init1 = new Init (1); var init2 = new Init (2); init1.x2; // 3 init2.x2; // 3
原型对象上添加一个x2
属性,结果,实例对象都共享了该属性。
原型对象的作用,就是定义所有实例对象共享的属性和方法。这也是它被称为原型对象的原因,而实例对象可以视作从原型对象衍生出来的子对象。
Init.prototype.add = function () { console.log(x1 + x2); };
上面代码中,Init.prototype
对象上面定义了一个add
方法,这个方法将可以在所有Init
实例对象上面调用。
构造函数的继承
第一种写法
- 第一步是在子类的构造函数中,调用父类的构造函数。
function Sub(value) { Super.call(this); this.prop = value; }
在实例上调用父类的构造函数Super
,就会让子类实例具有父类实例的属性。
- 第二步,是让子类的原型指向父类的原型,这样子类就可继承父类原型。
Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; Sub.prototype.method = '...';
要将Sub.prototype
赋值为Object.create(Super.prototype)
,而不是直接等于Super.prototype
。
否则后面两行对Sub.prototype
的操作,会连父类的原型Super.prototype
一起修改掉。
第二种写法
Sub.prototype
等于一个父类实例。
Sub.prototype = new Super();
子类会具有父类实例的方法, 但有时可能不是我们需要的,不推荐