Javascript JS函数返回函数,共享应该是私有的数据
我试图创建一个返回另一个函数的函数。当每个内部函数运行时,我需要单独的信息,但这并没有发生。我知道这个解释不是很好,所以我举了一个小例子Javascript JS函数返回函数,共享应该是私有的数据,javascript,function,Javascript,Function,我试图创建一个返回另一个函数的函数。当每个内部函数运行时,我需要单独的信息,但这并没有发生。我知道这个解释不是很好,所以我举了一个小例子 var testFn = function(testVal) { return (function(testVal) { var test = testVal; this.getVal = function() {
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return that;
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());
这将输出2,2。我想要的是输出2,4。我知道这并没有得到很好的解释,所以如果不清楚我想要实现什么,有人能解释为什么变量似乎在两个函数之间共享吗
像这样谢谢你
var testFn = function(testVal) {
var test = testVal
return {
getVal: function() {
return test
}
}
};
var ab = testFn (4)
var ac = testFn (2)
console.log(ab.getVal(),ac.getVal()) //4 //2
代码中的问题是this.getVal()
/返回this
因为“this”指的是全局范围/窗口
设置b=testFn(2)
这会导致覆盖a
s方法getVal
,因为它们都引用全局对象,并且始终共享相同的方法getVal
因此,它们共享相同的闭包并输出2
console.log(“相同:”+(Window.a==Window.b))//true
console.log(“相同:”+(a==b))//true
你可以看到,如果你稍微改变一下:
var testFn = function(testVal) {
var x = {}
return (function(testVal) {
var test = testVal;
x.getVal = function () {
return test;
}
return x
})(testVal);
}
var a = testFn(4);
var b = testFn(2);
console.log(b.getVal(), a.getVal());//4 2
它突然起作用,因为它会返回两个不同的对象(顺便说一句,您甚至不需要外部闭包)
console.log(“相同:”+(a==b))//false
以下是JSB/
我希望你能理解,我不擅长解释
如果有什么不清楚的地方,发表评论,我会尝试更新答案,你得到的结果是(2,2),因为当你这样做的时候
var that = this;
实际得到的是全局对象(窗口),包含javascript代码中所有全局方法和变量的对象。
(请注意,未嵌套在对象或函数下的每个变量都是全局变量,
每个未嵌套在对象下的函数都是全局函数,这意味着嵌套在函数下的函数仍然是全局函数 因此,当您设置:
var test = testVal;
this.getVal = function() {
return test;
}
实际上,您在全局对象中设置了函数“getVal”,在下一次运行中,您将再次设置相同的函数-覆盖第一次运行。为了达到您想要的效果,我建议创建和对象,并在内部函数中返回它(正如@glutlat在我之前建议的那样): 这样,在外部函数中,我们创建了一个对象,其中包含一个名为“getVal”的内部函数,该函数返回传递给外部函数(testVal)的变量。 如果你想玩它,这里有一个
(感谢@glutlat介绍这个网站,我从未听说过它,它真的很酷:D)这个问题归结到JavaScript中调用函数的上下文 在另一个函数中调用的函数在全局范围的上下文中执行 在您的示例中,您有以下代码:
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
})(testVal);
}
正在全局范围上调用内部函数,因此此
引用全局对象。在JavaScript中,在另一个函数中执行的函数的作用域设置为全局作用域,而不是它所在的函数的作用域。这往往会让开发人员绊倒(至少,我是这样)
为了论证起见,我们假设这是在浏览器中,因此this
引用窗口
对象。这就是为什么会记录两次2
,因为第二次运行时,This.getVal
会覆盖运行var a=testFn(4)时定义的getVal
方法代码>
JavaScript作用域位于函数级别,因此每个函数都有自己的作用域:
var x = 3;
function foo() {
var x = 2;
console.log(x);
};
console.log(x); //gives us 3
foo(); // logs 2
因此,您要做的是在testFn
函数的上下文中运行该内部函数,而不是在全局范围内。可以使用运行具有特定上下文的函数。我还录制了一个更详细地讨论这个问题的视频。call
的基本用法是:
function foo() {...}.call(this);
在此
的上下文中执行foo
。因此,第一步是确保在正确的上下文中调用内部函数,testFn
方法的上下文
var testFn = function(testVal) {
return (function(testVal) {
var test = testVal;
this.getVal = function() {
return test;
}
return this;
}.call(this, testVal);
}
调用的第一个参数是上下文,以及作为参数传递给函数的任何参数。因此,现在在正确的范围内调用内部函数,它不会将getVal
添加到全局范围,这是朝着正确方向迈出的一步:)
下一步,尽管您还需要确保每次调用testFn
,您都在一个新的作用域中这样做,所以当您第二次调用testFn
时,您不会覆盖this.getVal
。您可以使用new
关键字执行此操作。当您执行var foo=new testFn()
时,您将创建并执行testFn
的一个新实例,从而创建一个新范围
您现在需要做的就是将a
和b
的声明更改为:
var a = new testFn(4);
var b = new testFn(2);
现在是console.log(b.getVal(),a.getVal())代码>将根据需要提供2
,4
我提出了一个建议,这将有助于澄清问题。请注意此示例如何全局和在函数中定义this.x
,并查看哪些被记录。玩一玩,希望它会有用。ha,谢谢你这么说!哈哈,那是因为我把这个例子从我的实际代码中删掉了,好吧,让我大笑起来work@JamieHutber对实际问题有什么好的解释吗?不客气=)我是在JSFIDLE关闭时发现的,结果我更喜欢它,主要是因为内置的控制台和样式。
var a = new testFn(4);
var b = new testFn(2);