一、工厂模式
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("jianweis", 22, "software Engineer"); person1.sayName(); //jianweis工厂模式是一种广为人知的设计模式。函数createPerson()能够接受的函数来构建一个所含所有必要信息的Person对象。可以无数次调用这个函数,而每次它都会返回一个包含三个属性的一个方法的对象。工厂模式虽然解决了创建多个相似对象的问题,但是却没有解决对象识别的问题(即怎样知道一个对象的类型)。于是又有了新的模式出现。(资料取自JavaScript高级编程)
二、构造函数模式
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } } var person2 = new Person('jianweis', 22, 'student'); var person3 = new Person('least2727', 22, 'student'); person2.sayName(); //jianweis person3.sayName(); //least2727从以上代码我们可以看出构造函数与工厂模式的不同:
1.没有显示地创建对象(new object())
2.直接将属性和方法赋值给了this对象
3.没有return语句
而且按照惯例,构造函数的首字母要大写,例如上面的Person,而非构造函数则不需要大写。
大家也可以注意到当我们创建一个构造函数的实例时,我们使用了new操作符,那么new操作符在使用的过程中做了些什么呢,是以下4个步骤:
1.创建一个新对象(new object())
2.将构造函数的作用域赋值给新对象(例如上面代码,this指向person2和person3)
3.执行构造函数中的代码(为这个函数添加新属性)
4.返回新对象
每调用一次构造函数都会创建一个新的实例,而这个实例的constructor属性都会指向所调用的构造函数,例如上面代码的person2和person3的constructor会指向构造函数Person
console.log(person2.constructor == Person); //true console.log(person3.constructor == Person); //true console.log(person2 instanceof Person); //true console.log(person3 instanceof Person); //true创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。
但是正如上面所说的每调用一次构造函数就会创建一个新的实例,这就代表了构造函数中的方法在每次创建构造函数时都会重新创建一次,这样说的话不同实例的同名方法其实是不一样的,就像上面代码的sayName方法,在person2和person3里面是不一样的方法:
console.log(person2.sayName == person3.sayName); // false我们并不需要创建多个能够完成相同任务的Function实例。怎么解决呢,我们可以将函数定义转移到构造函数外面来解决这个问题。
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName(){ alert(this.name); } var person2 = new Person('jianweis', 22, 'student'); var person3 = new Person('least2727', 22, 'student'); person2.sayName(); //jianweis person3.sayName(); //least2727 console.log(person2.sayName == person3.sayName); // true这个例子里,我们将sayName函数的定义转移到构造函数的外部。而在构造函数的内部,我们将sayName属性设置成等于全局的sayName函数,这样一来,由于构造函数的sayName成为一个指针,不管创建多少实例都会指向同一个函数。可是这样子新的问题又来了:如果对象需要很多方法我们就得在全局中创建相对应的方法,这样不仅没有分装性可言而且很容易造成全局污染,这无疑是犯了大忌。怎么办呢,不用担心,这个我们可以使用原型模式来解决,由于原型模式的内容较多,我将在别的文章讲解。
