7中创建对象的方式(工厂模式、构造函数模式、原型模式、动态原型模式等分析)

1、工厂模式

// 定义工厂函数
function createPerson(name, age, hobby) {
// 创建一个临时object对象
var obj = new Object();
// 将工厂函数的参数赋值给临时对象
obj.name = name;
obj.age = age;
obj.hobby = hobby;
obj.sayName = function() {
console.log("我的名字叫:"+this.name);
}
// 返回这个包装好的临时对象
return obj;
}
//使用工厂函数创建对象
var p1 = createPerson('Tom', 12, "sing");
var p2 = createPerson('mayra', 18, "draw");

解决问题:用于创建的批量相似对象

2、构造函数模式

// 定义构造函数
function Person(name, age, hobby) {
this.name = name;
this.age = age;
this.hobby = hobby;
this.sayName = function() {
console.log("我的名字叫:"+this.name);
}
}
// 使用构造函数实例化
var p1 = new Person('Tom', 12, "sing");
var p2 = new Person('mayra', 18, "draw");

步骤分析:

  1. 使用new关键字在内存中创建一个新对象;
  2. 将构造函数的this指向这个新对象;
  3. 使用this为这个对象添加属性和方法
  4. 返回这个对象

解决的问题:构造函数可以将实例化的对象标识为一种特定的类型

存在的问题:相同的方法每次实例化都要重新创建一遍,浪费内存

3、原型模式

// 定义构造函数
function Person() {

}
// 定义原型
Person.prototype = {
constructor: Person, //重写constructor
name: 'Tom',
books: ['数学','英语'], // 引用类型
country: "china", // 共享属性
sayName: function () { // 共享方法
console.log("我的名字叫:" + this.name);
},
};
// 使用构造函数实例化
var p1 = new Person();
var p2 = new Person();
p1.books.push('语文');
console.log(p1.books); // '数学','英语','语文'
console.log(p2.books); // '数学','英语','语文' p1实例影响到p2!!!

问题:属性和方法都定义在了原型上,1、不能传参构造不同属性的对象 2、对于包含引用类型值的属性来说,实例之间会相互影响

这种单独使用原型模式的方法基本没人使用!

4、构造函数模式和原型模式组合使用(默认使用的模式!!!)

// 定义构造函数
function Person(name, age, hobby) {
this.name = name;
this.age = age;
this.hobby = hobby;
this.books = ['数学','英语']; //引用类型
}
// 定义原型(定义共享的属性)
Person.prototype = {
constructor: Person, //重写constructor
country: "china", // 共享属性
sayName: function () { // 共享方法
console.log("我的名字叫:" + this.name);
},
};
// 使用构造函数实例化
var p1 = new Person('Tom', 12, "sing");
var p2 = new Person('mayra', 18, "draw");
p1.books.push('语文');
console.log(p1.books); // '数学','英语','语文'
console.log(p2.books); // '数学','英语' p1实例不会影响到p2!!!
console.log(p1.country); // china
console.log(p2.country); // china
p1.sayName(); // 我的名字叫:Tom
p2.sayName(); // 我的名字叫:mayra

解决了构造函数模式共享方法多次创建问题,也解决了原型模式出现引用类型属性时存在的问题,目前最为常用的方式

5、动态原型模式

特点:将所有信息都封装在构造函数类,动态初始化原型

// 定义构造函数
function Person(name, age, hobby) {
this.name = name;
this.age = age;
this.hobby = hobby;
// 判断当前是否具有sayName方法,没有就初始化原型添加该方法
if(typeof this.sayName != 'function') {
// 这个只会在第一次使用构造函数时执行
Person.prototype.sayName = function () {
console.log("我的名字叫:" + this.name);
}
}

}
// 使用构造函数实例化
var p1 = new Person('Tom',13,'sing');
var p2 = new Person('bob',16,'draw');
p1.sayName();
p2.sayName();

解决问题:这样构造函数更像一个整体

6、寄生构造函数模式

function Person(name, age, hobby) {
// 创建一个临时object对象
var obj = new Object();
// 将参数赋值给临时对象
obj.name = name;
obj.age = age;
obj.hobby = hobby;
obj.sayName = function() {
console.log("我的名字叫:"+this.name);
};
// 返回这个包装好的临时对象
return obj;
}
//使用函数创建对象
var p1 = new Person('Tom', 12, "sing");
var p2 = new Person('mayra', 18, "draw");

其实就是构造函数样子的工厂模式,意义不大,不推荐使用

7、稳妥构造函数模式

function Person(name) {
// 创建一个临时object对象
var obj = new Object();

obj.sayName = function() {
console.log(this.name);
};
// 返回这个包装好的临时对象
return obj;
}
//函数创建对象
var p1 = new Person('Tom');
var p2 = new Person('mayra');
p1.sayName(); //Tom 只能通过这一种方式访问name的值

用处:提供固定访问成员的方法,适合在某些安全执行环境

以上不同环境下适合使用不同的模式创建对象,4、5两种模式较为常用。

posted @ 2018-07-28 22:27  -柒孟-  阅读(265)  评论(0)    收藏  举报