都0202年了,你还不知道javascript有几种继承方式?
// 父类构造函数 function Parent(color) { this.color = color; this.print = function() { console.log(this.color); } }
现在要编写一个子类函数来继承这个父类,如下:
// 子类构造函数 function Son(color) { Parent.call(this, color); }
上面代码可以看到,子类Son是通过Parent.call的方式去调用父类构造函数,然后把this对象传进去,执行父类构造函数之后,子类Son就拥有了父类定义的color和print方法。
调用一下该方法,输出如下:
// 测试 var son1 = new Son('red'); son1.print(); // red var son2 = new Son('blue'); son2.print(); // blue
function Flower() { this.colors = ['黄色', '红色']; this.print = function () { console.log(this.colors) } } function Rose() { Flower.call(this); } var r1 = new Rose(); var r2 = new Rose(); console.log(r1.print()); // [ '黄色', '红色' ] console.log(r2.print()); // [ '黄色', '红色' ]
我们现在有一个基类Flower,它有一个属性colors,现在我们把某一个实例的colors值改一下:
r1.colors.push('紫色'); console.log(r1.print()); // [ '黄色', '红色', '紫色' ] console.log(r2.print()); // [ '黄色', '红色' ]
-
优点:所有的基本属性独立,不会被其他实例所影响;
-
缺点:所有希望共享的方法和属性也独立了,没有办法通过修改父类某一处来达到所有子实例同时更新的效果;同时,每次创建子类都会调用父类构造函数一次,所以每个子实例都拷贝了一份父类函数的内容,如果父类很大的话会影响性能;
function Parent() { this.color = 'red'; this.print = function() { console.log(this.color); } } function Son() { }
我们有一个父类和一个空的子类;
Son.prototype = new Parent(); Son.prototype.constructor = Son;
接着我们把子函数的原型属性赋值给了父函数的实例;
var son1 = new Son(); son1.print(); // red
Son.prototype = new Parent(); Son.prototype.constructor = Son;
function Flower() { this.colors = ['黄色', '红色']; this.print = function () { console.log(this.colors) } } function Rose() {} Rose.prototype = new Flower(); Rose.prototype.constructor = Rose; var r1 = new Rose(); var r2 = new Rose(); console.log(r1.print()); // [ '黄色', '红色' ] console.log(r1.print()); // [ '黄色', '红色' ] r1.colors.push('紫色'); console.log(r1.print()); // [ '黄色', '红色', '紫色' ] console.log(r2.print()); // [ '黄色', '红色', '紫色' ]
-
优点:很好的实现了方法的共享;
-
缺点:正是因为什么都共享了,所以导致一切的属性都是共享的,只要某一个实例进行修改,那么所有的属性都会变化
function Parent(color) { this.color = color; } Parent.prototype.print = function() { console.log(this.color); } function Son(color) { Parent.call(this, color); } Son.prototype = new Parent(); Son.prototype.constructor = Son; var son1 = new Son('red'); son1.print(); // red var son2 = new Son('blue'); son2.print(); // blue
var obj = { color: 'red', print: function() { console.log(this.color); } }; var son1 = Object.create(obj); son1.print(); // red var son2 = Object.create(obj); son2.print(); // red
寄生式继承本质上还是原型链继承,Object.create(obj);方法意思是以obj为原型构造对象,所以寄生式继承不需要构造函数,但是同样有着原型链继承的优缺点,也就是它把所有的属性和方法都共享了。
function Parent(color) { this.color = color; } Parent.prototype.print = function() { console.log(this.color); } function Son(color) { Parent.call(this, color); } Son.prototype = Object.create(Parent.prototype); Son.prototype.constructor = Son; var son1 = new Son('red'); son1.print(); // red var son2 = new Son('blue'); son2.print(); // blue