构造函数模式:
ECMAScript中的构造函数可以用来创建特定类型的对象,也可以创建
自定义的构造函数,从而自定义对象类型的属性和方法。参考例2:
例2:
function Person(name,age){
this.name=name;
this.age=age;
this.getName=function(){
alert(this.name);
}
}
var person1=new Person("Tim",35);
var person2=new Person("Bob",40);
person1.getName(); //Tim
person2.getName(); //Bob
alert(person1); //Object
alert(person2); //Object
alert(person1 instanceof Person); //true,person1是Person的一个实例
alert(person2 instanceof Person); //true,person2是Person的一个实例
alert(person1.constructor == Person); //true,person1有一个构造函数属性,指向Person
alert(person2.constructor == Person); //true,person1有一个构造函数属性,指向Person
将例2的代码与之前的构造函数的相比较,可以发现以下几点不同:
(1)没有显示的创建对象;
(2)直接将属性和方法赋值给this对象;
(3)没有return语句。
按照惯例:构造函数始终应该以一个大写字母开头,而非构造函数应该以一个小写
字母开头。
对于上面的例2,可以发现:要创建Person的新实例,必须使用new操作符。其创建
的主要步骤为:
(1)创建一个新对象;
(2)将构造函数的作用域赋给新对象(此时this指向的是这个新对象)
(3)执行构造函数中的代码;
(4)返回新对象。
构造函数胜过工厂模式的地方在于:构造函数的实例除了是对象之外,还是一种特殊
的构造函数类型(可使用instanceof进行验证)。
构造函数的缺点:
使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。对于例2而言,
添加如下代码:
代码2: alert(person1.getName==person2.getName); //false
通过之前的了解,对象的方法可以类比为一个指针,指向内存中特定区域的函数,由代码2,
可以发现:即是是由同一个构造函数所创建的实例,他们的方法都会被重新创建,而不管
该方法是否完成同样的功能。
对于代码2,我们可以尝试做如下的修改:
代码3:
function Person(name,age){
this.name=name;
this.age=age;
this.getName=getName;
}
function getName(){
alert(this.name);}
var person1=new Person("Tim",35);
var person2=new Person("Bob",40);
person1.getName(); //Tim
person2.getName(); //Bob
alert(person1.getName==person2.getName); //true
若将方法定义在函数外,即是定义为一个全局函数,因为函数是对象,函数名是指针,
此时通过构造函数创建的两个实例的方法是相同的。但又带来了一个更现实的问题:如果
构造函数要定义很多方法,那么使用上述方法就需要创建更多的全局函数,那这个构造函
数就毫无封装性可言。
此时我们可以考虑运用原型模式来解决这个问题。