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.提供的答案,我用以下方式更新答案:
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())
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;
}