这个JavaScript闭包函数如何在没有全局变量的情况下重用一个对象?

Nob*_*ita 11 javascript closures

我决定向前迈出一步,试图理解Javascript并再次阅读Javascript:The Good Parts.这是第一个疑问:

假设我想避免使用全局变量因为它们是邪恶的,所以我有以下内容:

var digit_name = function(n) {
 var names = ['zero','one','two','three'];
 return names[n];
}
Run Code Online (Sandbox Code Playgroud)

D.Crockford声称这很慢,因为每次调用函数时,names都会完成一个新的实例化.所以,他通过这样做转移到闭包解决方案:

var digit_name = function () {
  var names = ['zero', 'one', 'two', 'three'];
  return function (n) {
    return names[n];
  }
}();
Run Code Online (Sandbox Code Playgroud)

这使得names变量存储在内存中,因此每次调用时都不会实例化它digit_name.

我想知道为什么?当我们打电话时digit_name,为什么第一行被"忽略"?我错过了什么?这里到底发生了什么?

我的这个例子不仅仅出现在书中,而是出现在这个视频上(第26分钟)

(如果有人想到更好的头衔,请酌情建议......)

Ell*_* B. 11

我确定你的意思是让你的第二个例子函数立即执行(即自调用)函数,如下所示:

var digit_name = (function () {
  var names = ['zero', 'one', 'two', 'three'];
  return function (n) {
    return names[n];
  }
})();
Run Code Online (Sandbox Code Playgroud)

区别在于具有闭包的范围链.JavaScript中的函数具有范围,因为它们将查找未在函数本身内声明的变量的父函数.

在JavaScript中声明函数内部的函数时,会创建一个闭包.封闭描述了范围.

在第二个示例中,digit_name设置为等于自调用函数.该自调用函数声明该names数组并返回一个匿名函数.

digit_name 因此变成:

function (n) {
  //'names' is available inside this function because 'names' is 
  //declared outside of this function, one level up the scope chain
  return names[n];
}
Run Code Online (Sandbox Code Playgroud)

从您的原始示例中,您可以看到names在返回的匿名函数(现在是digit_name)的范围链中向上声明了一个.当匿名函数需要时names,它会在范围链中向上移动,直到找到声明的变量 - 在这种情况下,names在范围链上找到一个级别.

关于效率:

第二个例子是更有效的,因为names仅声明一次-当自调用函数火灾(即,无功digit_name =(函数(){...})()).当digit_names被调用时,它会查找作用域链直到找到names.

在您的第一个示例中,names每次digit_names调用时都会声明,因此效率较低.

图形示例:

你从道格拉斯Crockford的提供的例子是一个非常艰难的例子来学习封锁和范围链是如何工作的时候下手了-很多东西打包成一个代码少量.我建议考虑看看倒闭的视觉解释,像这样的:http://www.bennadel.com/blog/1482-A-Graphical-Explanation-Of-Javascript-Closures-In-A-jQuery- Context.htm