jny*_*len 79 javascript function-declaration
为什么这些例子中的第一个不起作用,但所有其他例子都不起作用?
// 1 - does not work
(function() {
setTimeout(someFunction1, 10);
var someFunction1 = function() { alert('here1'); };
})();
// 2
(function() {
setTimeout(someFunction2, 10);
function someFunction2() { alert('here2'); }
})();
// 3
(function() {
setTimeout(function() { someFunction3(); }, 10);
var someFunction3 = function() { alert('here3'); };
})();
// 4
(function() {
setTimeout(function() { someFunction4(); }, 10);
function someFunction4() { alert('here4'); }
})();
Run Code Online (Sandbox Code Playgroud)
sle*_*man 179
这不是范围问题,也不是封闭问题.问题是,在相互理解的声明和表达式.
JavaScript代码,因为即使是Netscape的第一个版本的JavaScript和微软的第一个版本,它也分两个阶段处理:
阶段1:编译 - 在此阶段,代码被编译为语法树(以及字节码或二进制,具体取决于引擎).
阶段2:执行 - 然后解释解析的代码.
函数声明的语法是:
function name (arguments) {code}
Run Code Online (Sandbox Code Playgroud)
参数当然是可选的(代码也是可选的,但重点是什么?).
但JavaScript也允许您使用表达式创建函数.函数表达式的语法类似于函数声明,除了它们是在表达式上下文中编写的.表达式是:
=符号右侧(或:对象文字)的任何内容.().与声明不同的表达式在执行阶段而不是编译阶段处理.因此,表达的顺序很重要.
所以,澄清一下:
// 1
(function() {
setTimeout(someFunction, 10);
var someFunction = function() { alert('here1'); };
})();
Run Code Online (Sandbox Code Playgroud)
第1阶段:编译.编译器看到变量someFunction已定义,因此它创建它.默认情况下,创建的所有变量都具有undefined值.请注意,此时编译器无法分配值,因为这些值可能需要解释器执行某些代码才能返回要分配的值.在这个阶段,我们还没有执行代码.
第2阶段:执行.解释器看到您想要将变量传递someFunction给setTimeout.它确实如此.不幸的是,当前的值someFunction是未定义的.
// 2
(function() {
setTimeout(someFunction, 10);
function someFunction() { alert('here2'); }
})();
Run Code Online (Sandbox Code Playgroud)
第1阶段:编译.编译器看到你声明一个名为someFunction的函数,因此它创建它.
阶段2:解释器看到您要传递someFunction给setTimeout.它确实如此.当前值someFunction是其编译的函数声明.
// 3
(function() {
setTimeout(function() { someFunction(); }, 10);
var someFunction = function() { alert('here3'); };
})();
Run Code Online (Sandbox Code Playgroud)
第1阶段:编译.编译器看到您已声明变量someFunction并创建它.和以前一样,它的值是未定义的.
第2阶段:执行.解释器将匿名函数传递给setTimeout以便稍后执行.在这个函数中,它看到你正在使用变量,someFunction因此它为变量创建了一个闭包.此时,值someFunction仍未定义.然后它会看到你分配一个函数someFunction.此时,值someFunction不再是未定义的.1/100秒后,setTimeout触发并调用someFunction.由于它的值不再是未定义的,因此可行.
案例4实际上是案例2的另一个版本,其中someFunction引入了一些案例3.当传递给setTimeout时,由于它被声明,它已经存在.
补充说明:
您可能想知道为什么setTimeout(someFunction, 10)不在someFunction的本地副本和传递给setTimeout的副本之间创建闭包.答案是,JavaScript中的函数参数总是,如果它们是数字或字符串,则总是按值传递,或者通过引用传递给其他所有参数.所以setTimeout实际上并没有传递someFunction传递给它的变量(这意味着创建了一个闭包),而是只获取someFunction引用的对象(在本例中是一个函数).这是JavaScript中用于破解闭包的最广泛使用的机制(例如在循环中).
| 归档时间: |
|
| 查看次数: |
18258 次 |
| 最近记录: |