JavaScript fundamentals confusion
嗨,我正在努力理解JavaScript的基本原理,并坚持一个条件。
1 2 3 4 5 6 7 8 | var foo = 1; function bar(){ foo = 10; return; function foo(){} } bar(); alert(foo); |
这里,
1 2 3 4 5 6 7 | var foo = 1; function bar(){ foo = 10; return; } bar(); alert(foo); |
在bar函数中,如果我要删除函数
请帮忙,如果有人能解释我为什么?
这叫做javascript提升
我会尽量详细解释的。这就是我们拥有的
1 2 3 4 5 6 7 8 9 10 | var foo = 1; function bar(){ foo = 10; return; function foo(){} } bar(); alert(foo); |
口译员将把这个改写为
1 2 3 4 5 6 7 8 9 10 | var foo = 1; function bar(){ function foo(){} // this is also equal to var foo = function(){}; foo = 10; return; } bar(); alert(foo); |
所以现在解释一下提升的代码。
1 2 3 4 5 6 7 8 9 10 | var foo = 1; // global variable; function bar(){ var foo = function(){}; // foo is local variable of type function foo = 10; // foo is changed to hold a number return; } bar(); alert(foo); // you alert global variable. |
如您所见,如果代码
当你的
bar() 中有function foo(){} 时,你甚至没有触及全局变量。因此提醒1 。当你没有
function foo(){} 时,你会碰到全局变量,因此会提醒10 。现在我希望你能理解输出。
编写此函数时:
1 2 3 4 5 | function bar(){ foo = 10; return; function foo(){} } |
javascript读到:
1 2 3 4 5 | function bar(){ function foo(){} foo = 10; return; } |
函数
所以你的警报给你1,因为你从不更新全局变量。
I know after return statement ,function foo() will not execute.
那不是真的。
函数声明被提升。
In bar function , If I will remove function foo(). then alert(foo) will give me 10
您不再具有名为
比较:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | (function() { console.log("Version 1"); var foo = 1; function bar() { console.log("At top of bar, foo is" + foo); foo = 10; console.log("After assignment in bar, foo is" + foo); return; function foo() {} } bar(); console.log("Global foo is" + foo); }()); (function() { console.log("Version 2"); var foo = 1; function bar() { console.log("At top of bar, foo is" + foo); foo = 10; console.log("After assignment in bar, foo is" + foo); return; } bar(); console.log("Global foo is" + foo); }()); |
这里的问题是吊装和关闭。
声明
如果
如果存在
1 2 3 4 5 6 7 8 | var foo = 1; function bar(){ console.log(typeof foo) // function return; function foo() {} } bar(); alert(foo); |
反对:
1 2 3 4 5 6 7 8 | var foo = 1; function bar(){ console.log(typeof foo) // number return; // function foo() {} } bar(); alert(foo); |
所以基本上发生的事情就好像你已经宣布了
1 2 3 4 5 6 7 8 9 | var foo = 1; function bar(){ var foo; foo = 10; return; function foo(){} } bar(); alert(foo); |
因此,事实上,
In addition to my previous answer in the same thread I am
adding another answer to put in more details about the Hoisting
feature in JavaScript as the previous answer is already accepted by the OP for its content.
首先,让我们熟悉范围是什么
范围在javascript中
Javascript初学者最困惑的一个原因是范围界定。实际上,这不仅仅是初学者。我见过很多经验丰富的javascript程序员,他们不完全理解范围。Javascript中范围界定如此混乱的原因是它看起来像C族语言。考虑以下C程序:
1 2 3 4 5 6 7 8 9 10 11 | #include <stdio.h> int main() { int x = 1; printf("%d,", x); // 1 if (1) { int x = 2; printf("%d,", x); // 2 } printf("%d ", x); // 1 } |
这个程序的输出是1,2,1。这是因为C和C族的其余部分具有块级范围。当控件进入一个块(如if语句)时,可以在该范围内声明新变量,而不影响外部范围。在JavaScript中不是这样。在Firebug中尝试以下操作:
1 2 3 4 5 6 7 | var x = 1; console.log(x); // 1 if (true) { var x = 2; console.log(x); // 2 } console.log(x); // 2 |
在这种情况下,Firebug将显示1、2、2。这是因为javascript具有函数级作用域。这与C族截然不同。块(如if语句)不会创建新的作用域。只有函数才能创建新的作用域。
对于许多习惯于C语言、C++语言、C语言或Java语言的程序员来说,这是意外的和不受欢迎的。幸运的是,由于javascript函数的灵活性,这里有一个解决方案。如果必须在函数内创建临时作用域,请执行以下操作:
1 2 3 4 5 6 7 8 9 10 | function foo() { var x = 1; if (x) { (function () { var x = 2; // some other code }()); } // x is still 1. } |
这个方法实际上非常灵活,可以在任何需要临时作用域的地方使用,而不仅仅是在block语句中。但是,我强烈建议您花时间真正理解和欣赏JavaScript范围。它非常强大,是我最喜欢的语言特征之一。如果你理解范围界定,提升对你来说会更有意义。
声明、姓名和起重
在javascript中,名称以四种基本方式之一进入作用域:
- 函数声明:它们的形式为
function foo() {} 。 - 变量声明:采用
var foo; 的形式。 - 函数声明和变量声明总是被javascript解释器无形地移动("提升")到其包含范围的顶部。
- 显然,函数参数和语言定义的名称已经存在。这意味着这样的代码:
前任:
1 2 3 4 | function foo() { bar(); var x = 1; } |
实际解释如下:
1 2 3 4 5 | function foo() { var x; bar(); x = 1; } |
结果表明,包含声明的行是否会被执行并不重要。以下两个功能是等效的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function foo() { if (false) { var x = 1; } return; var y = 1; } function foo() { var x, y; if (false) { x = 1; } return; y = 1; } |
注意声明的分配部分没有被提升。只有名字被提升。这与函数声明不同,整个函数体也将被提升。但是请记住,有两种正常的方法来声明函数。考虑以下javascript:
1 2 3 4 5 6 7 8 9 10 11 | function test() { foo(); // TypeError"foo is not a function" bar(); //"this will run!" var foo = function () { // function expression assigned to local variable 'foo' alert("this won't run!"); } function bar() { // function declaration, given the name 'bar' alert("this will run!"); } } test(); |
在这种情况下,只有函数声明的主体被提升到顶部。"foo"这个名字被提升了,但是尸体被留在后面,在执行过程中被分配。
这包括了提升的基础。这个答案的100%全部归功于本·切丽。我不想在我的答案中发布这个链接,因为链接可能会断开,我发现这完全是信息性的,对于任何一个JavaScript开发人员都是必须阅读的。