《JavaScript设计模式》——第9章 JavaScript设计模式9.1 Constructor(构造器)模式

    xiaoxiao2024-08-14  93

    本节书摘来自异步社区《JavaScript设计模式》一书中的第9章,第9.1节, 作者: 【美】Addy Osmani 译者: 徐涛 更多章节内容可以访问云栖社区“异步社区”公众号查看。

    第9章 JavaScript设计模式

    在本章中,我们将探索一些经典与现代设计模式的JavaScript实现。

    开发人员通常想知道他们是否应该在工作中使用一种“理想”的模式或模式集。这个问题没有明确的唯一答案,我们研究的每个脚本和 Web 应用程序可能都有它自己的个性化需求,我们需要思考模式的哪些方面能够为实现提供实际价值。

    例如,一些项目可能会受益于观察者模式提供的解耦好处(这可以减少应用程序的某些部分对彼此的依赖度),而有些项目可能只是因为太小,而根本无需考虑解耦。

    也就是说,一旦我们牢牢掌握了设计模式和与它们最为相配的具体问题,那么将它们集成到我们的应用程序架构中就会变得更加容易。

    在本节中将要探索的模式包括:

    Constructor(构造器)模式;Module(模块)模式;Revealing Module(揭示模块)模式;Singleton(单例)模式;Observer(观察者)模式;Mediator(中介者)模式;Prototype(原型)模式;Command(命令)模式;Facade(外观)模式;Factory(工厂)模式;Mixin(混入)模式;Decorator(装饰者)模式;Flyweight(享元)模式。

    9.1 Constructor(构造器)模式

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

    Object构造器用于创建特定类型的对象—准备好对象以备使用,同时接收构造器可以使用的参数,以在第一次创建对象时,设置成员属性和方法的值(见图9-1)。

    9.1.1 对象创建在JavaScript中,创建新对象的两种常用方法如下所示:

    //下面每种方式都将创建一个新的空对象

    var newObject = {};

    // object构造器的简洁记法

    var newObject = new Object();

    在Object构造器为特定的值创建对象封装,或者没有传递值时,它将创建一个空对象并返回它。

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

    // ECMAScript 3兼容方式// 1. “点”语法// 设置属性

    newObject.someKey = "Hello World";

    // 获取属性

    var key = newObject.someKey;

    // 2. 中括号语法// 设置属性

    newObject["someKey"] = "Hello World";

    // 获取属性

    var key = newObject["someKey"];

    // 只适用ECMAScript 5 的方式// 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", "Delorean"); defineProp(person, "dateOfBirth", "1981"); defineProp(person, "hasBeard", false);

    //4.Object.defineProperties// 设置属性

    Object.defineProperties(newObject, { "someKey": { value: "Hello World", writable: true }, "anotherKey": { value: "Foo bar", writable: false } });

    // 可以用1和2中获取属性的方式获取3和4方式中的属性正如我们将在本书稍后看到的,这些方法甚至可以用于继承,如下所示:

    // 用法// 创建赛车司机driver对象,继承于person对象

    var driver = Object.create(person);

    // 为driver设置一些属性

    defineProp(driver, "topSpeed", "100mph");

    // 获取继承的属性

    console.log(driver.dateOfBirth);

    // 获取我们设置的100mph的属性

    console.log(driver.topSpeed);

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

    在构造器内,关键字this引用新创建的对象。回顾对象创建,基本的构造器看起来可能是这样的:

    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 civic = new Car("Honda Civic", 2009, 20000); var mondeo = new Car("Ford Mondeo", 2010, 5000);

    // 打开浏览器控制台,查看这些对象上调用的toString()方法的输出

    console.log(civic.toString()); console.log(mondeo.toString());

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

    值得庆幸的是,因为有很多ES3和ES5兼容替代方法能够用于创建对象,所以很容易解决这个限制问题。

    9.1.3 带原型的Constructor(构造器)JavaScript中有一个名为prototype的属性。调用JavaScript构造器创建一个对象后,新对象就会具有构造器原型的所有属性。通过这种方式,可以创建多个Car对象,并访问相同的原型。因此我们可以扩展原始示例,如下所示:

    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 civic = new Car("Honda Civic", 2009, 20000); var mondeo = new Car("Ford Mondeo", 2010, 5000); console.log(civic.toString()); console.log(mondeo.toString());

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

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)