面向对象的程序设计
工厂模式
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("Tom", 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("Tom", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
//Person函数有下列用法
// 当作构造函数使用
var person = new Person("Tom", 29, "Software Engineer");
person.sayName(); //"Tom"
// 作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到window
window.sayName(); //"Greg"
// 在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Jerry", 25, "Nurse");//在o的作用域中调用
o.sayName(); //"Jerry"
person1和person2分别保存着Person的不同实例。他们都有一个constructor(构造函数)属性,指向Person。
person1.constructor == person2.constructor;//true
构造函数在声明函数属性时,每个Person 实例都包含一个不同的Function 实例。
alert(person1.sayName == person2.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 person1 = new Person("Tom", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
alert(person1.sayName == person2.sayName);//true,person1 和person2 对象就共享了在全局作用域中定义的同一个sayName()函数,但这并不是最好的解决方案
原型模式
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。
function Person(){
}
//添加Person的原型属性和方法
Person.prototype.name = "Tom";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Tom"
var person2 = new Person();
person1.sayName(); //"Tom"
alert(person1.sayName == person2.sayName); //true