1、组合使用构造函数模式和原型模式
创建自定义类型的最常见类型,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度的节省了内存。另外,这种混合模式还支持向构造函数传递参数。代码如下所示:
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ["saly", "geil"]; } Person.prototype = { constructor: Person, sayName: function () { alert(this.name); } } var person1 = new Person("zxj", 29, "Software Engineer"); var person2 = new Person("Greg", 29, "Doctor"); person1.friends.push("van"); alert(person1.friends); //"saly","geil","van" alert(person2.friends); //"saly","geil" alert(person1.friends === person2.friends) //false alert(person1.sayName === person2.sayName) //true
这种构造函数与原型混合的模式,是目前ECMAScript中使用最广泛、认同度最高的一种创建自定义的方法。
2、动态原型模式
有OO经验的开发人员看见将构造函数和原型独立开来,很可能感到困惑。动态原型模式则是致力解决这个问题,它将所有的信息都封装在构造函数中,而通过在构造函数中初始化原型(仅在有必要情况下),这样同时保持了构造函数模式与原型模式的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否初始化原型。如下:
function Person(name,age,job){ //属性 this.name=name; this.age=age; this.job=job; //方法 if(typeof this.sayName != "function") { Person.prototype.sayName=function(){ alert(this.name); }; } } var person = new Person("zxj","29","Software Engineer"); person.sayName();
3、寄生构造函数模式
通常,在前面几种模式都不适用的情况下,可以使用寄生构造函数模式。这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后返回新创建的对象。但从表面看,它似乎很像典型的构造函数。代码如下:
function Person(name,age,job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function () { alert(this.name); } return o; } var person = new Person("zxj", 29, "Software Engineer"); person.sayName();
除了使用new操作符并使用的的包装函数是构造函数之外,这个模式和工厂模式一模一样。
关于寄生构造函数模式,有一点需要说明:首先,返回的对象与构造函数或者构造函数的原型属性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此,不能依赖instanceof操作符来确定对象类型。
4、稳妥构造函数模式
所谓稳妥对象就是没有公共属性,方法也不引用this的对象。稳妥对象最适合在一些安全的环境中(这些环境禁止使用this和new),或者在防止数据被其它应用程序改动时使用。稳妥构造函数模式和寄生构造函数模式的不同点:一、新创建的对象的实例方法不引用this;二、不使用new操作符调用构造函数。
function Person(name, age, job) { //创建要返回的对象 var o = new Object(); //可以在这里定义私有变量和函数 //添加方法 o.sayName = function () { alert(name); } //返回对象 return o; } var person = new Person("zxj", 29, "Software Engineer"); person.sayName();