Javascript高级程序设计读书笔记(第六章)
第6章 面向对象的程序设计
6.2 创建对象
创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤:
- 创建一个新对象;
- 将构造函数的作用域赋给新对象;
- 执行构造函数中的代码;
- 返回新对象。
构造函数的问题:每个方法都要在每个实例上重新创建一遍;
理解原型对象:
无论何时,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针。如下面的例子:
function Person() { } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function() { alert(this.name); }; var person1 = new Person(); person1.sayName(); //"Nicholas"
如下图所示展示了各个对象之间的关系:
6.3 继承
6.3.1 原型链继承
基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法。即让子类的原型对象等于父类的实例。
存在的问题:
function SuperType() { this.colors = ["red", "blue", "green"]; } function SubType() { } SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //red,blue,green,black; var instance2 = new SubType(); alert(instance2.colors); //red,blue,green,black
colors本来属于SuperType的实例属性,但是SubType继承以后就变成了SubType的原型属性,结果是SubType的所有实例都会共享这一个colors属性。
另一个问题:在创建子类型的实例时,不能向超类型的构造函数中传递参数。
6.3.2 借用构造函数
基本思想:在子类型构造函数的内部调用超类型构造函数。如下所示:
1 function SuperType() { 2 this.colors = ["red", "blue", "green"]; 3 } 4 5 function SubType() { 6 SuperType.call(this); //继承了SuperType 7 } 8 9 var instance1 = new SubType(); 10 instance1.colors.push("black"); 11 alert(instance1.colors); //red,blue,green,black; 12 13 var instance2 = new SubType(); 14 alert(instance2.colors); //red,blue,green
相对于原型链,借用构造函数有一个很大的优势,可以在子类型构造函数中向超类型构造函数传递参数。
借用构造函数的问题:
方法都在构造函数中定义,因此函数复用无从谈起,所有类型都只能使用构造函数模式。在超类型的原型中定义的方法,对子类型而言也是不可见的。
6.3.3 组合继承
组合继承是将原型链和借用构造函数的技术组合到一起,从而发挥二者之长的一种继承模式。基本思想是:使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承。
1 function SuperType(name) { 2 this.name = name; 3 this.colors = ["red", "blue", "green"]; 4 }; 5 6 SuperType.prototype.sayName = function() { 7 alert(this.name); 8 }; 9 10 function SubType(name, age) { 11 //继承属性 12 SuperType.call(this, name); 13 this.age = age; 14 } 15 16 //继承方法 17 SubType.prototype = new SuperType(); 18 19 SubType.prototype.sayAge = function() { 20 alert(this.age); 21 } 22 23 var instance1 = new SubType("Nicholas", 29); 24 instance1.colors.push("black"); 25 alert(instance1.colors); 26 instance1.sayName(); //Nicholas 27 instance1.sayAge(); //29 28 29 30 var instance2 = new SubType("Grey", 27); 31 alert(instance2.colors); //"red,blue,green" 32 instance2.sayName(); //Grey 33 instance2.sayAge(); //27
组合继承避免了原型链和借用构造函数的缺陷,成为Javascript中最常用的继承模式
6.3.4 原型式继承