JavaScript:闭包中自动getter和setter中的默认参数,不带eval?

JavaScript:闭包中自动getter和setter中的默认参数,不带eval?,javascript,closures,Javascript,Closures,注意:此问题是最近提出的问题的后续问题 这个问题的要点如下:“如果不使用eval语句,如何为闭包中的作用域变量自动提供getter和setter?”。海报上提供了代码,演示了如何使用eval执行此操作,用户给出了以下不需要eval的内容: function myClosure() { var instance = {}; var args = Array.prototype.slice.call(arguments); args.forEach(function(arg) {

注意:此问题是最近提出的问题的后续问题

这个问题的要点如下:“如果不使用
eval
语句,如何为闭包中的作用域变量自动提供getter和setter?”。海报上提供了代码,演示了如何使用
eval
执行此操作,用户给出了以下不需要
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;
};
这个问题是关于如何使用上述函数设置/获取作用域变量的默认值

如果我们简单地向变量
v3
添加一个默认值,我们会得到以下结果:

function myClosure() {
  var v3 = 2
  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") // make setters/getters for all vars
test.v1(16).v2(2) // give new values to v1, v2
console.log(test.v1() + test.v2() + test.v3()) // try to add with default v3
// 18v3
我没想到会这样

那么如何为变量提供默认值呢

注意:请构建以下在初始化时生成getter/setter的实现(允许代码作者预先定义所有应该有getter和setter的变量)

问题:
如何在此设置(代码块上方)中使用自动getter和setter的默认值?

您的意思是:

函数myClosure(…vars){
常量实例={};
vars.forEach(varArg=>{
让name=未定义;
设值=未定义;
if(typeof varArg=='string')
{
name=varArg;
}
其他的
{
name=Object.keys(varArg)[0];
value=varArg[name];
}
实例[名称]=函数(d){
if(!arguments.length)返回值;
数值=d;
返回实例;
};
})
返回实例;
}
const test=myClosure(
{“v1”:1},
“v2”,
{“v3”:3},
);
//打印一些默认值。
log(test.v1());
log(test.v2());
test.v1(16).v2(42)//给v1,v2赋予新值

console.log(test.v1()、test.v2()、test.v3())
注意:我发布自己的答案仅供参考。我不会将此作为问题的答案

根据@H.B.提供的答案,我用以下方式更新答案:

  • getter和setter是在闭包本身初始化时生成的
  • 使getter和setter生产函数更加混乱,以允许更懒惰的变量定义
  • 实例现在是一个函数,而不是一个对象

    function myClosure() {
    
      var instance =  function () {
          console.log(this.v1(), this.v2(), this.v3())
      };
    
      var publicVariables =[ 'v1', 'v2', {'v3': 3} ] 
    
      function setup() {
    
    
        var args = Array.prototype.slice.call(arguments);
    
        // if called with a list, use the list, 
        // otherwise use the positional arguments
    
        if (typeof args[0] == 'object' && args[0].length) { args = args[0] }
    
        args.forEach(function(arg) {
            var name, value
            if(typeof arg == 'object') {
            name = Object.keys(arg)[0]
            value = arg[name]
          } else {
            name = arg
            value = undefined
          }
    
          instance[name] = function(d) {
            if (!arguments.length) return value;
            value = d;
            return instance;
          }; // end instance function
        }) // end for each
      } // end setup
      setup(publicVariables)
      return instance; 
    }
    
    var test = myClosure().v1(10).v2(2)
    console.log(test.v1(), test.v2(), test.v3())
    test.v1(20).v3(1)
    console.log(test.v1(), test.v2(), test.v3())
    
  • 该问题的要点如下:“如何在闭包中自动为作用域变量提供getter和setter,而不使用eval语句”。海报上提供了演示如何使用eval的代码,用户给出了不需要eval的答案

    不,没有
    eval
    ,您就不能这样做。这里所有不使用任何形式的
    eval
    的答案都不会访问作用域变量,而只是简单的属性——或者它们创建自己的局部变量

    提供默认值非常简单:

    function myClosure(...args) {
      var instance =  {v3: 2};
    //                 ^^^^^ not a `var`
      for (const arg of args) {
        let val = instance[arg];
        instance[arg] = function(d) {
          if (!arguments.length) return val;
          val = d;
          return instance;
        };
      }
      return instance;
    }
    

    FWIW,很难理解你的问题,因为(带着歉意!)它有点漫无边际。(我看到有人对此投了反对票,这可能就是原因。)保持问题的简洁和切中要害有助于人们帮助你。@T.J.Crowder我会尽力澄清的。部分原因是因为这个问题是对先前问题和答案的后续。简而言之,目标是拥有一个闭包,其中包含一些具有默认值的作用域变量。此外,对于这些变量,自动生成getter和setter“closure”是如何定义的?我觉得这个词很奇怪,特别是考虑到它的其他更常见的含义。@H.B.这个定义可能有点混乱。我使用的是函数闭包(其中一个变量的作用域在函数内部,可以通过调用函数闭包的函数来更新。@H.B.:,应该会有帮助。(编辑:啊,这是您期望的意思。:-)排序。但是,现在所有值都必须具有默认值?因此,没有办法使用
    var
    语句(例如,在
    instance=…
    语句上方)@sumneun:如果您不提供默认值,那么该值一开始将是未定义的。你所说的var语句是什么意思?(删除了代码中的一个默认值)是的,这更接近我的意思。不过我想我的目标是()请看一看。我会给别人一天时间,让他们在给出答案之前发表自己的想法。至于var语句,我的意思是,例如,
    函数myClosure(){var v1,v2=3,v3…}
    顺便调整了代码以匹配链接示例的调用签名。我看到了,非常时髦。如果可以,我会再次投票。你真的很擅长编程。比我原来的帖子用
    eval
    在一个字符串上写得更清晰了。+1我很欣赏你的回答,我明确地回答说,如果没有eval,我所要求的东西是不可行的,这是不可能的,而且我的回答可以说明你的解决方案中的默认值。理想情况下,instance(返回的内容)是一个函数,它对允许更改默认值的变量执行某些操作。以你的专业知识,你有没有建议(在这里或其他答案中)这样做的方法?@SumNeuron你将如何使用该功能
    test(“v1”,16)
    test(“v3”)==2
    ?假设公共变量(在我们的示例中,v1、v2、v3)是
    myClosure
    返回的函数的参数,例如
    function(){return(v1+v2)%v3}
    @SumNeuron在该示例中,它们是自由变量,而不是参数?你的意思是
    函数(v1,v2,v3){return(v1+v2)%v3}
    ?不,我的意思是作为范围在
    myClosure
    下的自由变量。鉴于这里提供的示例,它们必须是
    (instance.v1()+instance.v2())%instance.v3())
    ,因此我倾向于将它们限定在闭包中
    function myClosure(...args) {
      var instance =  {v3: 2};
    //                 ^^^^^ not a `var`
      for (const arg of args) {
        let val = instance[arg];
        instance[arg] = function(d) {
          if (!arguments.length) return val;
          val = d;
          return instance;
        };
      }
      return instance;
    }