返回变量作为构造函数

Returning a variable as a constructor function

本文关键字:构造函数 变量 返回      更新时间:2023-09-26

我是 JavaScript 的新手,有人建议我阅读《学习 JavaScript 设计模式》一书。我正在阅读工厂设计模式,遇到了以下困难,请看下面的脚本:

// 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 );

这是我为工厂设计模式找到的示例,现在我的问题是理解以下行。考虑到车辆类被定义为一个变量:

VehicleFactory.prototype.vehicleClass = Car;

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

return new this.vehicleClass( options );

好吧,这是我唯一的困难,一次又一次地运行代码,对我来说仍然没有意义。

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

当您想要返回类型为 Truck 的新对象时,您将使用以下代码:

return new Truck( options )

但是,在这种特定情况下,您想要的车辆类型由用户定义。因此,this.vehicleClass是指在返回值正上方的开关中定义的值。换句话说,vehicleClass将被替换为Car(或 Truck ),如果用户选择了car(或 Truck )。

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

我希望现在更清楚了。

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

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

JavaScript 的一大优点是能够将函数作为参数传递,而无需委托。

我希望这能让它更清楚一点。

问候

在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

资料来源:Stoyan StefanovJavaScript Patterns

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

new <expression>(<arguments>)

评估如下:

  1. 评估<expression>
  2. 呼叫new <result of 1>(<arguments>)

也就是说,您可以将任何表达式放在new和左括号之间,只要此表达式返回函数即可。

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

VehicleFactory.prototype.vehicleClass = Car;

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

this.vehicleClass = Car;

这在后续查找中有效地覆盖了prototypevehicleClass

 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的更好方法是这样的:

VehicleFactory.prototype.createVehicle = function ( options ) {
  var klass;    
  switch(options.vehicleType){
    case "car":
      klass = Car;
      break;
    case "truck":
      klass = Truck;
      break;
  }
  return new (klass || this.vehicleClass)( options );
};

主观地说,"设计模式"在javascript中并不是很惯用,如果你想要另一个阅读建议,试试JavaScript Allongé。