Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/448.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript JS函数返回函数,共享应该是私有的数据_Javascript_Function - Fatal编程技术网

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);