闭包是引用独立(自由)变量(在本地使用但在封闭范围内定义的变量)的函数。
如果我们使用MDM 中的此定义并将其应用于您的基本示例并在浏览器中运行它(没有 JSBin 或 JSFiddle)。
<html>
<head></head>
<body>
<script>
var outer = 2;
var addTo = function() {
var inner = 3;
return outer + inner;
};
console.dir(addTo);
</script>
</body>
</html>
如果我们看一下控制台,您将获得以下输出:

没有像 JSBin 这样的闭包,这是预期的行为。我们没有在本地使用任何变量,而是在封闭范围内定义的。outer
是在全局范围内定义的,而不是在封闭范围内。
现在,如果我们使用完全相同的代码,但将其插入到一个自动执行的匿名函数中:
<html>
<head>
</head>
<body>
<script>
(function (){
var outer = 2;
var addTo = function() {
var inner = 3;
return outer + inner;
};
console.dir(addTo);
})();
</script>
</body>
</html>
控制台输出如下:

outer
不再在全局范围内定义,而是在封闭范围内,即自执行匿名函数的范围内,并且在addTo
函数中本地使用。根据定义,它是一个闭包。
关于 JSBin 和 JSFiddle,出于安全原因,这两个站点都会在 iframe 中执行您的代码。在 JSBin 上,iframe 与您的代码如下所示:
<body>
<script>
try {var outer = 2;
var addTo = function() {
var inner = 3;
return outer + inner;
};
window.runnerWindow.proxyConsole.dir(addTo);
} catch (error) { throw error; }
</script>
</body>
如果我们看一下outer
,它不是在封闭范围内定义的。try
这里没有定义范围,因为 JavaScript 具有函数范围但没有块范围。正如预期的那样,正如您的测试所证明的那样,控制台中没有 Closure 元素。
另一方面,JSFiddle 在他的 iframe 中使用不同的代码来执行您的代码:
<head>
<script type="text/javascript">
window.onload=function(){
var outer = 2;
var addTo = function() {
var inner = 3;
return outer + inner;
};
console.dir(addTo);
}
</script>
</head>
在 JSFiddle 上,您的代码被包装在一个匿名函数中,该函数将onload
在窗口事件上执行。在这种情况下,您的outer
变量是在封闭范围内定义的本地使用的变量,并且是一个闭包。这就是为什么当您查看控制台时,您会在输出中看到一个闭包。