将变量作为构造函数返回。

时间:2015-03-17 07:48:24

标签: javascript

嘿伙计我是javascript的新手,我被建议阅读这本书learning javascript design patterns,我正在阅读工厂设计模式并遇到以下困难,请看下面的脚本:

// Types.js - Constructors used behind the scenes

// A constructor for defining new cars
function Car( options ) {

  // some defaults
  this.doors = options.doors || 4;
  this.state = options.state || "brand new";
  this.color = options.color || "silver";

}

// A constructor for defining new trucks
function Truck( options){
  this.state = options.state || "used";
  this.wheelSize = options.wheelSize || "large";
  this.color = options.color || "blue";
}


// FactoryExample.js

// Define a skeleton vehicle factory
function VehicleFactory() {}

// Define the prototypes and utilities for this factory

// Our default vehicleClass is Car
VehicleFactory.prototype.vehicleClass = Car;

// Our Factory method for creating new Vehicle instances
VehicleFactory.prototype.createVehicle = function ( options ) {

  switch(options.vehicleType){
    case "car":
      this.vehicleClass = Car;
      break;
    case "truck":
      this.vehicleClass = Truck;
      break;
    //defaults to VehicleFactory.prototype.vehicleClass (Car)
  }

  return new this.vehicleClass( options );

};

// Create an instance of our factory that makes cars
var carFactory = new VehicleFactory();
var car = carFactory.createVehicle( {
            vehicleType: "car",
            color: "yellow",
            doors: 6 });

// Test to confirm our car was created using the vehicleClass/prototype Car

// Outputs: true
console.log( car instanceof Car );

// Outputs: Car object of color "yellow", doors: 6 in a "brand new" state
console.log( car );

这是我为工厂设计模式找到的例子,现在我的问题是理解以下一行:

考虑到vehicleClass类被定义为变量:

VehicleFactory.prototype.vehicleClass = Car;

我不明白它是作为构造函数返回的:

return new this.vehicleClass( options );
好吧,这是我唯一的困难,一次又一次地运行代码,对我来说仍然没有意义。

如果有人能向我解释,我将不胜感激。

谢谢。

亚历山大

4 个答案:

答案 0 :(得分:1)

您分配给VehicleFactory.prototype.vehicleClass的内容不是实际class,而是对constructor function的引用。

要在JavaScript中创建对象,new运算符必须后跟构造函数。由于代码VehicleFactory.prototype.vehicleClass中的this.vehicleClass或更高版本包含对构造函数的引用,因此您可以使用new this.vehicleClass(options)创建新的车辆对象。

JavaScript的一大优势是能够将函数作为参数传递,而无需代理。

我希望这会让它更清晰一点。

问候

答案 1 :(得分:1)

这里返回的不是一个函数(你是对的,它没有意义)。返回的是一个新对象(请参阅new关键字)。

如果要返回类型为Truck的新对象,请使用代码:

return new Truck( options )

然而,在这种特定情况下,您想要的车辆类型由用户定义。所以this.vehicleClass指的是返回上方的开关中定义的值。换句话说,如果用户选择vehicleClass(分别为Car),则Truck将替换为car(分别为Truck)。

因此,将被调用的构造函数将是代码第一行中定义的CarTruck构造函数。

我希望现在更清楚了。

答案 2 :(得分:1)

在Javascript中函数是对象,因此可以将它们用作返回值。这意味着函数不需要因执行而返回某种数据值或数据数组。

函数可以返回另一个更专业的函数,或者它可以按需创建另一个函数,具体取决于某些输入。 这是一个简单的例子:一个函数做一些工作,可能是一些一次性初始化,然后处理它的返回值。返回的值恰好是另一个函数,也可以执行:

var setup = function () {
   alert(1);
   return function () {
        alert(2);
   };
};
// using the setup function
var my = setup(); // alerts 1
my(); // alerts 2

因为 setup()包装了返回的函数,所以它创建了一个闭包,你可以使用这个闭包来存储一些私有数据,这些数据可以由返回的函数访问,但不能访问外部代码。一个例子是一个计数器,每次调用它时都会给你一个递增的值:

var setup = function () {
    var count = 0;
    return function () {
        return (count += 1);
    };
};
// usage
var next = setup();
next(); // returns 1

来源:JavaScript PatternsStoyan Stefanov

在您的情况return new this.vehicleClass( options );中,返回一个新对象调用构造函数vehicleClass

答案 3 :(得分:1)

new <expression>(<arguments>)

的评估如下:

  1. 评估<expression>
  2. 致电new <result of 1>(<arguments>)
  3. 也就是说,只要此表达式返回一个函数,就可以在new和左括号之间放置任何表达式。

    顺便说一句,这段代码似乎没有以正确的方式做事。首先,它在原型上定义了一个属性:

    VehicleFactory.prototype.vehicleClass = Car;
    

    然后,在createVehicle中,它添加了一个具有相同名称的本地属性:

    this.vehicleClass = Car;
    

    在后续查找中有效覆盖prototype的{​​{1}}:

    vehicleClass

    设计 a = createVehicle(); // no `vehicleType` here, returns `Car` b = createVehicle({vehicleType: 'truck'}); // returns `Truck` c = createVehicle(); // no `vehicleType` here, but this time it returns `Truck`??? 的更好方法是这样的:

    createVehicle

    在主观上,“设计模式”在javascript中并不是非常惯用,如果你想要另一个阅读建议,请试试JavaScript Allongé