8

示例 JSFiddle,这样您就可以更好地了解http://jsfiddle.net/brsXL/3/上发生的事情(打开您的控制台并查看记录的vars对象)。

我正在为 JavaScript 中的特定数学子集构建解析器和计算机,它将表达式作为来自用户的字符串,并允许他们使用变量。为了使我的计算逻辑简单但允许使用变量,我创建了一个对象,它的作用类似于数字,但具有通过引用传递的好处。

var Variable = function(value) {
    this.value = value || null;
}
Variable.prototype.valueOf = function() {
    return this.value;
}

这样可以:

var a = new Variable(10);
console.log(a + 2); // = 12
console.log(a / 2); // = 5

但是,只要我希望执行任何形式的赋值操作,例如+=对象丢失并被针对对象的 value 属性的操作结果替换。例如

var a = new Variable(10);
console.log(a += 2); // = 12
console.log(a); // = 12

我需要它像这样工作的原因是因为我想使用相同的函数来处理数字和变量。我可以为每个赋值操作添加代码,但这对我来说不是最理想的,例如

var ops = {
   "+=" : function(a, b) {
      if (a instanceof Variable) {
         a.value += b;
      } else {
         a += b;
      }
      return a;
   },
   ...
}

但我更愿意写:

var ops = {
   "+=" : function(a, b) {
      return a += b;
   },
   ...
}

这可以做到吗?

4

1 回答 1

4

我宁愿写:

function(a, b) {
    return a += b;
}

这可以做到吗?

不,不可能将参考值作为单个变量传递。您总是需要使用对象属性。a在您的函数中始终是局部范围的,因此更改它不会影响外部世界。而且我不鼓励您尝试使您的运算符函数对更高范围的变量进行操作......</p>

我认为在您的情况下,对变量使用显式测试很好,因为赋值运算符实际上必须这样做。您不能分配给文字或其他值,只能分配给变量。甚至可能是

var ops = {
   "=" : function(a, b) {
      if (a instanceof Variable) {
         a.value = +b; // cast b to a number (from whatever it is)
         return a;
      } else {
         throw new Error("Invalid assignment to non-variable "+a);
      }
   },
   ...
}

此外,为避免代码重复,您可能不会写出所有复合赋值运算符。以通用方式定义它们:

["+", "-", "*", "/"].forEach(function(op) {
    ops[op+"="] = function(a, b) {
        return ops["="].call(this, a, ops[op].call(this, a, b));
    };
});

更新了 jsfiddle 演示

于 2013-10-23T11:44:52.657 回答