一、工厂模式
function createPerson(name, age){ var obj = new Object(); obj.name = name; obj.age = age; obj.display = function(){ alert(this.name); }; return obj; } var p1 = createPerson("jyy", 29); p1.display();
缺点:无法解决对象识别的问题,无法知道对下对象的类型
二、构造函数模式
function Person(name, age){ this.name = name; this.age = age; this.display = function(){ // 创建对象实例时会重复创建方法 console.log(name); } } var p1 = new Person("jyy", 29); p1.display();
console.log(p1 instanceof Person); // true
优点: 解决了对象识别的问题,可以使用instanceof判断对象的类型
缺点:每次创建一个对象实例,都会重复创建方法,这样的话方法是不共享的
三、原型模式
function Person(){} Person.prototype.name = "baby"; Person.prototype.age = "0"; Person.prototype.display = function(){ console.log(this.name); }; var p1 = new Person("jyy", 29); p1.display(); var p2 = new Person("wss", 28); p2.display(); console.log(p1.name === p2.name); // true 对象的属性也共享了
优点:解决了方法共享的问题
缺点:对象的属性也被共享,这也是为什么代码中两个对象的name是相同的
四、组合使用构造函数模式和原型模式
在上面的构造函数模式中没有解决方法的共享问题,而原型模式解决了共享问题,但是却将属性也共享了,那么将二者合并起来就可以完美解决
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.display = function(){ console.log(this.name); } var p1 = new Person("jyy", 29); p1.display();
这种混合的模式,是目前使用最广泛、认同度最高的创建自定义类型的方式。
五、动态原型模式
上面的混合模式是由两部分构成的,这样的话可能看上去不那么好看。这样的话,我们可以用动态原型模式将原型的初始化放在构造函数中。
function Person(name, age){ this.name = name; this.age = age; if(typeof this.showName != "function"){ Person.prototype.showName = function(){ console.log(this.name); }; Person.prototype.showAge = function(){ console.log(this.age); }; } } var p1= new Person("jyy", 29); p1.showName(); // jyy p1.showAge(); // 29
在构造函数中判断方法的类型是否是function,若不是function,则表示还未创建。一旦创建,则所有的原型方法都会创建,因此只需检验一个方法名称即可。
六、寄生构造函数模式
有时我们需要对一个现有的对象的创建额外的方法。比如想要在数组中新增一个方法,但是又不能直接修改Array,以免造成污染,这就可以使用该模式
该模式如下:
function Person(name, age){ var obj = new Object(); obj.name = name; obj.age = age; obj.display = function(){ console.log(this.name); } return obj; } var p1 = new Person("jyy", 29); // 与工厂模式不同就只有new p1.display();
如上可以看出该模式基本和工厂模式是一样的,唯一的不同就是Person是用new创建的。因为如果构造函数在不返回值的情况下,默认会返回新对象的实例,若存在返回值,则返回。
现在实现开头所说的在Array中添加自定义方法:
function SpecialArray(){ var values = new Array(); values.push.apply(values, arguments); values.toPipedString = function(){ return this.join("|"); } return values; } var color = new SpecialArray("red", "color"); console.log(color.toPipedString()); // red|color
同工厂模式一样,该模式一样不能确定对象类型。因此在可以使用其他模式的情况下,不要使用着这种模式
七、稳妥构造函数模式
该模式指没有公共属性,其方法也不引用this的对象。适合在安全的环境中,或防止数据被其他应用程序改动时使用(暂未找到应用场景)。
function Person(name, age){ var obj = new Object(); obj.display = function(){ console.log(name); }; return obj; } var p1 = Person("jyy", 29); p1.display();