一、工厂模式
function createPerson(name, age) { var o = new Object(); o.name = name; o.age = age; o.say = function () { alert(this.name); }; return o;
}
每次调用这个函数都会返回一个包含两个属性和一个方法的对象。
二、构造函数模式
js中的构造函数可以用来创建特定类型的对象,像object和array这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也是可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 this.say = function(){ 5 alert(this.name); 6 } 7 } 8 var person1 = new Person("xiaoming","18");
构造函数也是函数,只是调用他们的方式不同,任何函数,只要通过new操作符调用,则它就可以作为构造函数;不通过new操作符调用,则就是普通函数。
1、当做构造函数
1 var person1 = new Person("xiaoming",18); 2 person1.say(); // xiaoming
2、当做普通函数
1 Person("xiaozhu",20); //添加到window 2 window.say(); // xiaozhu
三、原型模式
我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象包含所有实例共享的属性和方法。按照字面意思,那么prototype就是通过调用构造函数而创建的对象实例的原型对象。使用它的好处是,可以让所有对象实例共享原型中所包含的属性和方法。
1 function Person(){} 2 Person.prototype.name="xiaoming"; 3 Person.prototype.age=18; 4 Person.prototype.say=function(){ 5 alert(this.name); 6 } 7 var person1=new Person(); 8 person1.say(); // xiaoming 9 var person2 = new Person(); 10 person2.say(); // xiaoming
然而当包含引用类型值的属性时,就会出现问题;
1 function Person(){} 2 Person.prototype.name="xiaoming"; 3 Person.prototype.age=18; 4 Person.prototype.eat=['苹果','橘子']; 5 Person.prototype.say=function(){ 6 alert(this.name); 7 } 8 var person1=new Person(); 9 10 alert(person1.eat); // 苹果 橘子 11 person1.eat.push("香蕉"); 12 var person2 = new Person(); 13 alert(person2.eat); // 苹果 橘子 香蕉
可以看到,eat属性是引用类型的值,当person1更改了eat数组,则在person2中也能反映出来,然而这并不是我们想要的结果。继续看。
四、组合使用构造函数和原型模式
这种方式能极大解决单独使用构造函数或者原型模式带来的问题。这种方式是目前使用最广泛的方法;组合使用,构造函数用来定义实例属性,原型模式用来定义方法和共享属性。这样每个实例都会有属于自己的实例属性副本,而且同时又共享着对方法的引用,最大限度的节省了内存。
1 function Person(name,age){ 2 this.name=name; 3 this.age=age; 4 this.eat=['苹果','橘子']; 5 } 6 Person.prototype.say=function(){ 7 alert(this.name); 8 } 9 var person1=new Person("xiaoming",18); 10 alert(person1.eat); // 苹果 橘子 11 person1.eat.push("香蕉"); 12 var person2 = new Person(); 13 alert(person2.eat); // 苹果 橘子