JavaScript:没有eval的闭包中的自动getter和setter?

时间:2018-03-25 08:02:24

标签: javascript closures

注意:关于JavaScript中的getter和setter有很多问题(请参阅Javascript Getters And SettersGetters and Setters in a function (javascript)Getters and Setters in JavaScript (Correct syntax ?)automatic getter and setter(with validation) in javascript,等等)。这些问题中的大多数都涉及Objects,少数问题涉及Closures,其中很少涉及自动生成getter和set。这个问题涉及后者。

answerautomatic getter and setter(with validation) in javascript可能是我所寻找的最接近的,但对我的用例来说并不理想。

目前,在我的关闭中,我有以下内容:

function myClosure() {
  var closureVar1, closureVar2

  function do () { ... }

  function setupSettersAndGetters() {

    var closureVariables = ['closureVar1', 'closureVar2']

    for (var i = 0; i < closuredVariables.length; i++) {

      var currentClosureVariable = closureVariable[i]
      var toEvaluateString = "                                                 \
      do." + currentClosureVariable + " = function(value){                     \
        if(!arguments.length) return " + currentClosureVariable + ";           \
        " + currentClosureVariable + " = value;                                \
        return setup;                                                          \
      };                                                                       \
      "
      eval(toEvaluateString)
    }
  }
  setupSettersAndGetters()
  return do;
}

这完全符合我的意愿,例如。

var test = myClosure()
test.closureVar1(10).closureVar2(2)
test.closureVar1() + test.closureVar2() // return 12

使用eval只有一个“微小”的问题,有些人detest

所以我的问题是,是否有更好的方法来处理这个并允许我按名称调用setter / getter,而不是使用字符串?

e.g。我可以使用中间函数,例如:

test.sget('closureVar1', 10) // set closureVar1 to 10
test.sget('closureVar2') // get closureVar2

但即使这样做,我想我仍然需要使用eval?我宁愿调用变量的名称......

思想?

1 个答案:

答案 0 :(得分:2)

您可以将传递给myClosure函数的参数...

var args = Array.prototype.slice.call(arguments);

...并使用它们来设置你的setter和getter:

args.forEach(function(arg) {
    instance[arg] = function(d) {
        if (!arguments.length) return arg;
        arg = d;
        return instance;
    };
});

这样,您可以传递所需的变量数量,同时避免使用eval

这是一个演示:

function myClosure() {
  var instance = {};
  var args = Array.prototype.slice.call(arguments);
  args.forEach(function(arg) {
    instance[arg] = function(d) {
      if (!arguments.length) return arg;
      arg = d;
      return instance;
    };
  })
  return instance;
};

var test = myClosure("v1", "v2", "v3")
test.v1(16).v2(2).v3(8)
console.log(test.v1() + test.v2() + test.v3())