使用Object构造函数和字面量都可以创建对象 ,但是同一个接口创建多个对象时候会产生大量重复代码;
//工厂模式
function createPerson(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 person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
构函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
}; }
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
对比上面工厂模式,构造函数模式
- 没有直接new一个对象
- 直接把属性和方法赋值给this
- 有 return语句
要创建Person的新实例必须使用new关键字,以这种方法调用构造函数回家里下面四个步骤
- 创建一个新对象
- 将构造函数的作用域赋给新对象(this指向这个新对象)
- 执行构造函数中的代码(添加属性和方法)
- 换回新对象
前面例子中person1,person2,分别为Person,的两个不同的实例,这两个实例都有一个constructor属性并且这个属性指向Person;
alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
但是上面的例子中构造函数模式也有问题;实例化两次为每个实例都创建了一个sayName方法,这两个sayName方法是两个不同的对象,
alert(person1.sayName == person2.sayName); //false
然而这两个sayName作用一样没必要创建两个;ECMAScript 中的函数就是一个对象每定义一个函数就是实例化一个对象;我们可以尝试把函数定义转移到构造函数之外;如下
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
alert(this.name);
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
这样他们就是用的同一个sayName函数;
然而这样在全局作用域定义的函数只在某个对象中引用,让这个全局作用与函数有点名不副实;并且当有多个方法那在全局作用域则要定义大量函数;
我们可以通过原型模式来解决这个问题
原型模式
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true