工厂模式
function createPerson(name, age, job) {
var p = new Object()
p.name = name;
p.age = age;
p.job = job;
p.sayName = function () {
alert(this.name)
}
return p;
}
var person1 = createPerson('Lusen', 26, 'coder')
var person2 = createPerson('Eugine', 26, 'teacher')
缺点:没有解决对象识别,所有的实例都指向一个原型
构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert(this.name)
}
}
var person1 = new Person('Lusen', 26, 'coder')
var person2 = new Person('Eugine', 26, 'teacher')
// 这两个对象都有一个constructor属性,都指向Person
person1.constructor === Person // true
person2.constructor === Person // true
person1 instanceof Person // true
创建构造函数的实例,必须使用new操作符,经历以下四步:
1. 创建一个新对象
2. 将构造函数的作用域赋给新对象(this指向了这个新对象)
3. 执行构造函数中的代码(为这个新对象添加属性)
4. 返回新对象
优点:实例可以识别为一个特定的类型
缺点:每次创建实例,每个方法都要创建一次
构造函数优化:
将sayName函数的定义转移到了构造函数外部,这样构造函数内部sayName包含的是一个指向外部函数的指针。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName = function(){
alert(this.name)
}
var person1 = new Person('Lusen', 26, 'coder')
var person2 = new Person('Eugine', 26, 'teacher')
优点:解决了每个方法都要被重新创建的问题
缺点:对象如果有多个方法,需要定义多个全局函数,自定义的引用类型没有封装性而言。
原型模式
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象。好处是让所有实例对象都共享它原型对象的属性和方法。
function Person() {
}
Person.prototype.name = 'Lusen'
Person.prototype.age = 26
Person.prototype.job = 'coder'
Person.prototype.sayName = function () {
alert(this.name)
}
var person1 = new Person()
person1.sayName() // Lusen
var person2 = new Person()
person2.sayName() // Lusen
优点:方法不会重新创建
缺点:1. 所有的属性和方法都共享 2. 不能初始化参数
原型模式优化
function Person() {
}
Person.prototype = {
constructor: Person,
name: 'Lusen',
sayName: function(){
alert(this.name)
}
}
var person1 = new Person()
组合模式
构造函数和原型模式组合:
构造函数用于定义实例属性,原型模式用于定义方法和共享的属性。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype = {
constructor: Person,
sayName: function () {
alert(this.name)
}
}
动态原型模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if (typeof this.sayName != 'function') {
Person.prototype.sayName = function () {
alert(this.name)
}
}
}
寄生构造函数模式
这种模式的基本思想是创建一个函数,函数的作用仅仅是封装创建对象的代码,最后返回对象,最后用new 操作符实例化。
function Person(name, age, job) {
var p = new Object()
p.name = name;
p.age = age;
p.job = job;
p.sayName = function () {
alert(this.name)
}
return p;
}
构造函数在不返回值得情况下,默认返回新对象实例。而在构造函数末尾添加一个return语句,可以重写构造函数返回的值。
如果我们要创建一个有额外方法的特殊数组,但是又不能直接修改Array构造函数可以使用这个模式
function SpecialArray() {
var values = new Array()
values.push.call(values, arguments)
values.toPipedString = function () {
return this.join('|')
}
return values;
}
var colors = new SpecialArray('red', 'blue', 'green');
稳妥构造函数模式
function person(name){
var o = new Object();
o.sayName = function(){
console.log(name);
};
return o;
}
var person1 = person('kevin');
person1.sayName(); // kevin
person1.name = "daisy";
person1.sayName(); // kevin
console.log(person1.name); // daisy
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用 this 的对象。
与寄生构造函数模式有两点不同:
- 新创建的实例方法不引用 this
- 不使用 new 操作符调用构造函数
稳妥对象最适合在一些安全的环境中。
稳妥构造函数模式也跟工厂模式一样,无法识别对象所属类型。