javaScript设计模式-构造器

Constructor(构造器) 模式

在经典面向对象编程语言中,Constructor是一种在内存已分配给该对象的情况下,用于初始化新创建对象的特殊方法。在javaScript中,几乎所有的东西都是对象,我们通常最感兴趣的就是object构造器。

对象创建

在JavaScript中创建对象有两种方式:

1
2
3
4
5
// 下面每种方式都将创建一个新的对象。
var newObject = {};

// object构造器的简洁记法
var newObject = new Object();

有四种方法可以将键值赋值给一个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// ECMAScript 3 兼容方式

// 1. "点"语法

// 设置属性
newObject.somekey = "hello world";

// 获取属性
var key = newObject.somekey;

// 2. 中括号语法

// 设置属性
newObject[somekey] = "hello world";

// 获取属性
var key = newObject = newObject[somekey];

// 只适用于 ECMAScript 5的方式
// 更多信息查看: http://kangax.github.com/es5-compat-table/

// 3. Object.defineProperty

// 设置属性
Object.defineProperty(newObject, "somekey", {
value: "for more control of the property's behavior",
writable: true,
enumerable: true,
configurable: true
});

// 如果上面看着麻烦,可以使用下面的简便方式
var defineProp = function(obj, key, value) {
config.value = value;
Object.defineProperty(obj, key, config);
}

// 使用上述方式,先创建一个空的person对象
var person = Object.create(null);

// 然后设置各个属性
defineProp(person, "car", "奔驰");
defineProp(person, "dateOfBirth", '1997');
defineProp(person, "hasBeard", false);

// Object.defineProperties

// 设置属性
Object.defineProperties(newObject, {
"somekey": {
value: "hello world",
writable: true,
},

"anotherkey": {
value: 'Foo bar',
writable: false,
}
});

// 可以用 1,2 中获取属性的方式获取 3 , 4 方法中的属性

这些方法是可以用于继承的,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
// 用法
// 创建赛车司机 driver 对象,继承于 person 对象
var driver = Object.create(person);

// 为driver 设置一些属性
defineProp(driver, "topSpeed", "100mph");

// 获取继承的属性
console.log(driver.dateOfBirth);

// 获取我们设置的 100mph 的属性
console.log(driver.topSpeed);
基本Constructor(构造器)

JavaScript 不支持类的概念,但它确实支持与对象一起用的特殊constructor(构造器)函数。通过在构造器前面加 new 关键字,告诉JavaScript像使用构造器一样实例化一个新对象,并且对象成员由该函数定义。

在构造器内,关键字this引用新创建的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Car(model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;

this.toString = function(){
return this.model + "has done " + this.miles + "miles";
};
}

// 用法

// 可以创建 car 的新实例
var BenZ = new Car("奔驰", 2019, 2000);
var mondeo = new Car("Ford Mondeo", 2010, 5000);

// 打开浏览器控制台,查看这些对象上调用的toString() 方法的输出
cosole.log(BenZ.toString());
console.log(mondeo.toString());

上面是一个简单的构造器模式版本,但是它有一些问题,其中一个问题就是,它使继承变的很困难,另一个问题是,同String() 这样的函数是为每个使用Car构造器创建的新对象而分别重新定义的。这不是最理想的,因为这种函数因该在素有的Car类型实例之间共享。

带原型的 Constructor(构造器)

Javascript中有一个名为 prototype 的属性。调用JavaScript构造器创建一个对象后,新对象就会具有构造器原型的所有属性。通过这种方式,可以创建多个Car对象,并访问相同的原型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Car(model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
}

// 注意这里我们使用 Object.prototype.newMethod 而不是 Object.prototype 是为了避免重新定义 prototype 对象

Car.prototype.toString = function(){
return this.model + "has done" + this.miles + " miles";
};

// 用法:
var BenZ = new Car("奔驰", 2019, 10000);
var mondeo = new Car("Ford Mondeo", 2000, 10000);

console.log(BenZ.toString());
console.log(mondeo.toSting());

现在toString()的单一实例就能够在所有Car对象之间共享。