对上一章节的工厂模式进行代码重写
1 function Human(name, sex) { 2 this.name = name; 3 this.sex = sex; 4 this.say = function () { 5 alert(this.name); 6 } 7 } 8 var man = new Human("汉武大帝", "男"); 9 var woman = new Human("王母娘娘","女");
看到Human没有.他的第一个字母大写了.这是一种语法约定.构造函数始终应该以一个大写字母开头,而非构造函数则以一个小写字母开头,用于区分构造函数和非构造函数.
要创建Human的实例,必须使用new操作符.这就会出现以下四个步骤:
1.创建一个新对象或变量.
2.将构造函数的作用域赋值给新变量或新对象.
3.执行构造函数中的代码
4.返回新对象.
1 alert(man instanceof Object);//true 2 alert(man instanceof Human); //true 3 alert(woman instanceof Object); //true 4 alert(woman instanceof Human); //true
这里的true很好的说明了:创建自定义的构造函数意味着将来可以将他的实例表示为一种特定的类型.而这正是构造韩式模式优于工厂模式的地方.
尽管如此,构造函数还是有自己的一些缺陷,或者说不足吧.
在man和woman中都有一个名为say()的方法,他们的功能一模一样.但是这两个方法却不是同一个Function()实例创建出来的.
1 function Human(name, sex) { 2 this.name = name; 3 this.sex = sex; 4 this.say = new Function("alert(this.name);"); 5 }
这就意味着如果需要n个实例,就要创建n个say的Function()实例.这样还是会造成资源的浪费.
继续对上面的代码经行优化,让这个say()方法只创建一次.共用一个引用.
1 function Human(name, sex) { 2 this.name = name; 3 this.sex = sex; 4 this.say = say; 5 } 6 function say() { 7 alert(this.name); 8 }
因为say包含一个指向函数的指针,因此Human的实例就共享了全局作用域中的同一个say()函数.但这个无法让人接受,
因为如果系统比较庞大的话,就会出现很多全局变量,一不小心就会有被改掉的危险.而我们封装的对象就没有封装性可言了.
接着就又有了原型模式了.下一章在接着说原型模式.