“故意”;冻结“;使用自执行函数的javascript变量
我在读一篇关于用“故意”;冻结“;使用自执行函数的javascript变量,javascript,Javascript,我在读一篇关于用node.js创建一个scraper的博客文章时,遇到了一个有趣的javascript代码,我想都想不起来了。这正是我想在我的脚本中使用的东西,但是作为一个新手,我不想在不知道他们首先做什么的情况下盲目地复制和粘贴代码 在该功能中: function main() { var a = 1; var f = function() { console.log(a); } a = 2; f(); } main(); 输出是2,因为var a在调用f()
node.js
创建一个scraper的博客文章时,遇到了一个有趣的javascript代码,我想都想不起来了。这正是我想在我的脚本中使用的东西,但是作为一个新手,我不想在不知道他们首先做什么的情况下盲目地复制和粘贴代码
在该功能中:
function main()
{
var a = 1;
var f = function() { console.log(a); }
a = 2;
f();
}
main();
输出是2
,因为var a
在调用f()
之前被更改
但是,在这个函数中
function main()
{
var a = 1;
var f = ( function(a) { return function() { console.log(a); } } )(a);
a = 2;
f();
}
main();
输出为1
。在上面链接的博文中对此有一个相当详细的解释,但我一生都搞不清楚这到底是为什么
这篇文章提到了传递到函数中的
var a
的范围-有人能详细说明这意味着什么吗?为什么有必要在var f
函数的末尾添加最后一个(a)
?当然,因此变量的范围是变量可能受到或可能影响的环境类型。因此,这将返回一个闭包,基本上是该函数的作用域或环境的快照。当您将所有内容封装在该闭包中时,可以将其视为一种情况,并且返回的函数之外的任何内容都不会影响其中的内容。现在,在本例中变量作用域“a”就是这一个函数。闭包可以是一个非常强大的工具,也是我真正喜欢JavaScript的原因之一 所以你有这个功能(用这种方式最清晰):
将函数包装为DE括号将使函数直接执行,这意味着函数将在将1分配给a
之后执行,但在分配2之前执行
换行后的(a)
是传递给函数的参数
因此传递给函数的值是a=1
在该函数中,返回另一个函数,该函数将记录a
(参数)的值,因此为1
通过将其分配给变量f,可以在函数执行时(即分配a=2
之前)将变量的状态保留在函数中
function main()
{
var f = ( function(a) { return function() { console.log(a); } } )(a);
a = 2;
f();
}
main();
var a=1代码>//添加了一个简单变量。。
var f=(函数(a){return function(){console.log(a);}})(a)代码>
这里的f
是一个自动执行函数,输入为。
在执行时,现在返回一个函数,该函数将a
作为输入变量。在此,您必须了解,您发送的是a的副本,而不是a。这意味着您正在扩展a
的范围,即使在函数执行之后也要使用它。但是根据f
传递的是一些参数,它不知道a
在外部发生了变化,因为您传递的是a
的副本,而不是a
。因此,它扩展了a
这就是它的工作原理。为了更好地理解这一点,请参阅JavaScript中的“Currying”主题。如果按照以下方式编写,您可能会理解它
function main()
{
var a = 1;
var f = ( function(b) { return function() { console.log(b); } } )(a);
a = 2;
f();
}
main();
这被称为变量阴影
——通过使用相同的名称命名函数的参数,我们将其隐藏在函数范围之外。如果我们没有像在我的示例中那样对变量进行阴影处理,那么代码是straighforward-我们正在定义返回函数(2)的函数(1),执行时返回的函数将打印传递给函数(1)的值。我们将a的当前值传递给函数,因此生成的代码是
var f = ( function(b) { return function() { console.log(b); } } )(1);
或
在JavaScript中,可以通过两种方式访问函数中的变量:
当它们是声明函数的执行上下文(范围)的一部分时
当调用函数时,它们作为参数传递
在后一种情况下,函数参数会隐藏作用域中具有相同名称的任何变量,因此对函数外部变量的更改不会对函数内部变量产生任何影响
在第二个代码示例中,通过立即调用外部函数,将内部函数分配给f
,并具有一致的a
值
但是,请注意,标量值比对象更容易阴影化;考虑这个代码:
var a = { x: 1 },
f = (function(a) {
return function() {
console.log(a);
};
}(a));
a.x = 123;
f(); // Object { x: 123 }
尽管值a
被保留,但它仍然是一个对象,因此对其属性的任何更改仍然可以在f()
中看到。也就是说,观察当a
本身而不是其属性发生变化时会发生什么:
a = { x: 456 };
f(); // Object { x: 456 }
这一次,a
的前一个值将被保留,函数外部的变量将被分配一个新值。这是一个函数表达式,可由立即调用。。。(a)
它还将'a'传递给函数(想象一个简单的函数调用)。其中,a
的值被保留,因为它现在是函数表达式范围的局部变量。变量通过VALUE传递,这是一个很好的解释。干杯
var a = { x: 1 },
f = (function(a) {
return function() {
console.log(a);
};
}(a));
a.x = 123;
f(); // Object { x: 123 }
a = { x: 456 };
f(); // Object { x: 456 }