下面的文字摘自《javascript:The Good Parts》的closure一节,没看懂,秦歌翻译的那本中文版也看了,还是没明白这段文字说的啥?希望各位SF的朋友能用你自己的理解帮我解释一下:
- 为什么第一段代码没有达到目的,不是说内部变量可以读取函数外部变量的吗?读取不到正确的标号,那怎么会弹出节点的数量呢?这个节点数量是怎么获取到的?
- 为什么第二段代码可以修正第一段代码的错误,加一个匿名函数它到底起到了什么作用?
============================
It is important to understand that the inner function has access to the actual variables of the outer functions and not copies in order to avoid the following problem:
Code View:
// BAD EXAMPLE // Make a function that assigns event handler functions to an array of nodes the wrong way. // When you click on a node, an alert box is supposed to display the ordinal of the node. // But it always displays the number of nodes instead. var add_the_handlers = function (nodes) { var i; for (i = 0; i < nodes.length; i += 1) { nodes[i].onclick = function (e) { alert(i); } } }; // END BAD EXAMPLE
The add_the_handlers function was intended to give each handler a unique number (i). It fails because the handler functions are bound to the variable i, not the value of the variable i at the time the function was made:
Code View:
// BETTER EXAMPLE // Make a function that assigns event handler functions to an array of nodes the right way. // When you click on a node, an alert box will display the ordinal of the node. var add_the_handlers = function (nodes) { var i; for (i = 0; i < nodes.length; i += 1) { nodes[i].onclick = function (i) { return function (e) { alert(i); }; }(i); } };
Now, instead of assigning a function to onclick, we define a function and immediately invoke it, passing in i. That function will return an event handler function that is bound to the value of i that was passed in, not to the i defined in add_the_handlers. That returned function is assigned to onclick.
需要明白 JS 里面的变量范围, 闭包解决的一个基本问题也是变量范围!
1. 在全局下面直接 var i = 1; 就属于全局变量, 全局变量可以在整个 window 范围内是可见的;
2. 在闭包里面 var c = 1; 就只有闭包内部可见;
3. 注意在哪里都行, 如果声明变量的时候不加 var 的话, 就是全局变量了;
4. 也就是回答你这个问题的答案, 闭包让这些变量的值始终保持在内存中 。 下面是个例子:
顺便说下面这种写法 js 里面是允许的, 至于全局变量为什么不好呢? 在做开发的时候, 应该尽量避免全局变量, 涉及到设计模式, 还有一些最佳实践, 可以 Google 下更多资料:
把下面的两段代码写个 test.html 页面做加深印象.