工厂模式
function createPerson(name, age) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.sayName = function () {
console.log(obj.name);
}
return obj;
}
var person = createPerson("zhangsan", 1);
无法实现实例之间共享一些方法和属性;无法识别对象类型(因为返回的是一个Object,而不是一个 Person类)
构造函数模式
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name);
}
}
var person = new Person("zhangsan", 1);
可以解决如何识别对象类型的问题;
新建一个实例(new)的过程:
- 创建一个新对象
- 将构造函数的作用域赋值给新对象(this 指向这个新对象)
- 执行构造函数中的代码
- 返回新对象
对于函数复用的问题,可以采用将函数定义在构造函数外部,构造函数中只需指向外部这个函数
function sayName() {
console.log(this.name);
}
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = sayName();
}
但定义在构造函数外面,如果对象需要定义很多方法,那么就要在构造函数外面定义多个全局函数,丝毫没有封装性可言。于是就提出了原型模式
原型模式
每个函数都有一个prototype属性,这个是一个指针类型,指向一个对象。这个对象的用处,可以让有这个函数创建的实例共享其属性和方法。
function Person() {
}
Person.prototype.name = 'zhangsan';
Person.prototype.age = 1;
Person.prototype.sayName = function () {
console.log(this.name);
};
Person.prototype.firends = ['李四']
var a = new Person();
var b = new Person();
a.sayName(); // zhangsan
b.sayName(); //zhangsan
a.firends.push('王五');
console.log(b.firends); // ['李四', '王五']
原型模式虽然可以实现不同实例之间的共享属性和共享方法,但有些属性和方法并不想设置为共享。对于这个问题,可以采用构造函数+原型混合的模式
构造函数+原型模式
在构造函数中定义不需要共享的属性和方法,在原型模式中定义共享的部分
function Person(name, age){
this.name = name;
this.age = age;
this.firends = [];
}
Person.prototype.sayName = function(){
console.log(this.name);
}
var a =new Person('zhangsan',1);
var b = new Person('lisi',2);
a.firends.push('王五');
console.log(a.firends); // ['王五']
console.log(b.firends); // []
但构造函数和原型分开定义,对于其他有OO语言经验的开发者可能会造成困惑,为此,提出了一种动态原型模式
动态原型模式
它将所有的内容封装到构造函数中,如
function Person(name, age){
this.name = name;
this.age = age;
// 在构造函数中增加判断,只有第一次执行时会触发。
if(typeof this.sayNmae !='function'){
Person.prototype.sayName = function(){
console.log(this.name);
}
}
}
在以上几种模式都不适用的情况下,可以使用寄生构造函数模式
寄生构造函数模式
function Person(name, age){
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function(){
console.log(this.name);
}
return o
}
var a = new Person('zhangsan', 1);
这中模式的思想时创建一个函数,该函数的作用仅仅时封装创建对象的代码,然后再返回新创建的对象。除了使用new操作符之外和,工厂模式其实一模一样。构造函数在不设返回值的情况下,返回新对象的实例。而通过在构造函数的末尾添加一个return,可以重写调用构造函数时返回的值。
稳妥构造函数模式
道格拉斯发明了一种稳妥对象,所谓的稳妥对象,指没有公共属性,而且方法中也不引用this的对象。稳妥对象最适合在一些安全环境(一些禁用this和new的环境)中使用
稳妥构造函数遵循与寄生构造函数相似的模式,但又两点不同:一是新创建对象的实例方法不引用this,二是不使用new操作符调用构造函数。可以将上面的Person重写如下
function Person(name,age){
var o = new Object();
// 可以定义私有变量和函数
//添加方法
o.sayName = function(){
console.log(name); // 这里是使用闭包
}
return o;
};
参考
红宝书