您好我正在尝试理解JavaScript基础知识,并且陷入了一个条件。
var foo = 1;
function bar(){
foo = 10;
return;
function foo(){}
}
bar();
alert(foo);
这里alert(foo)
会给我1
,我知道在return语句之后,函数foo()将不会执行。但现在如果改变代码:
var foo = 1;
function bar(){
foo = 10;
return;
}
bar();
alert(foo);
在条形函数中,如果我将删除函数foo()
。然后alert(foo)
会给我10
请帮助,如果有人能解释我为什么?
答案 0 :(得分:7)
这称为 Javascript悬挂
我将尝试详细解释它。这就是我们所拥有的
var foo = 1;
function bar(){
foo = 10;
return;
function foo(){}
}
bar();
alert(foo);
解释器会将其重写为
var foo = 1;
function bar(){
function foo(){} // this is also equal to var foo = function(){};
foo = 10;
return;
}
bar();
alert(foo);
现在向您解释提升的代码。
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.
正如您所看到的,代码function foo(){}
是否存在,它被视为bar()
范围内的局部变量,foo
的任何更改都被视为局部变量更改。 。
当您在function foo(){}
中 bar()
时,您甚至没有触及全局变量..因此提醒1
。
当您没有 function foo(){}
时,您正在触及全局变量,因此会发出警告10
。
现在我希望你理解输出..
答案 1 :(得分:4)
我知道在return语句之后,函数foo()将不会执行。
那不是真的。
函数声明已悬挂。
function foo(){}
创建一个名为foo
的局部变量(为其分配新函数),然后foo = 10
覆盖它。您永远不会测试foo
变量的值。
在bar函数中,如果我将删除函数foo()。然后警报(foo)会给我10个
您不再拥有名为foo
的局部变量,因此您将覆盖具有相同名称的全局变量。
比较
(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);
}());

答案 2 :(得分:4)
编写此功能时:
function bar(){
foo = 10;
return;
function foo(){}
}
javascript读取此内容:
function bar(){
function foo(){}
foo = 10;
return;
}
函数foo
已创建到本地函数bar
中。当您编写foo = 10
时,您将覆盖本地范围中的函数foo
而不是全局变量。
因此,您的警报会给您1,因为您永远不会更新全局变量。
答案 3 :(得分:3)
声明function foo(){}
被悬挂,意味着在这种情况下,即使它是在函数末尾写的,它也可以在范围内的任何地方使用,包括在它的定义之前。
如果function foo(){}
不存在,则语句foo = 10;
将覆盖全局范围中定义的foo
。因此全球foo === 10
。
如果存在function foo(){}
,则语句foo = 10;
只会覆盖本地范围内的函数foo
,因此全局foo
无法触及全局foo === 1
{1}}
var foo = 1;
function bar(){
console.log(typeof foo) // function
return;
function foo() {}
}
bar();
alert(foo);
反对:
var foo = 1;
function bar(){
console.log(typeof foo) // number
return;
// function foo() {}
}
bar();
alert(foo);
答案 4 :(得分:2)
所以基本上发生的事情就好像你已宣布var foo = 10
因为javascript中的函数声明被提升了
complier看到你的代码如下。
var foo = 1;
function bar(){
var foo;
foo = 10;
return;
function foo(){}
}
bar();
alert(foo);
所以实际上foo = 10
永远不会覆盖全局foo
;
它保持在功能的本地。
所以警报将通过全球警报。
答案 5 :(得分:1)
除了我在同一个帖子中的 previous answer 之外,我也是 添加另一个答案以提供有关提升的更多详细信息 JavaScript中的功能,因为OP的内容已经接受了上一个答案。
首先让我们对范围界定感到满意
使用JavaScript进行范围界定
JavaScript初学者最困惑的一个原因是范围界定。实际上,它不仅仅是初学者。我遇到了很多经验丰富的JavaScript程序员,他们并不完全了解范围。范围界定在JavaScript中如此混乱的原因是因为它看起来像一个C系列语言。考虑以下C程序:
#include <stdio.h>
int main() {
int x = 1;
printf("%d, ", x); // 1
if (1) {
int x = 2;
printf("%d, ", x); // 2
}
printf("%d\n", x); // 1
}
此程序的输出将为1,2,1。这是因为C和C系列的其余部分具有块级范围。当控件进入块(例如if语句)时,可以在该范围内声明新变量,而不会影响外部范围。在JavaScript中不是这种情况。在Firebug中尝试以下内容:
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功能的灵活性,有一种解决方法。如果必须在函数中创建临时范围,请执行以下操作:
function foo() {
var x = 1;
if (x) {
(function () {
var x = 2;
// some other code
}());
}
// x is still 1.
}
此方法实际上非常灵活,可以在需要临时范围的任何地方使用,而不仅仅在块语句中使用。但是,我强烈建议您花时间真正理解并理解JavaScript范围。它非常强大,是我最喜欢的语言功能之一。如果您了解范围界定,那么吊装将对您更有意义。
声明,姓名和提升
在JavaScript中,名称以四种基本方式之一进入范围:
Language-defined:
默认情况下,所有范围都是名称this和arguments。
Formal parameters:
函数可以命名形式参数,这些参数的作用域是该函数的主体。
function foo() {}
。var foo;
。例如:
function foo() {
bar();
var x = 1;
}
实际上是这样解释的:
function foo() {
var x;
bar();
x = 1;
}
事实证明,包含声明的行是否会被执行并不重要。以下两个函数是等效的:
function foo() {
if (false) {
var x = 1;
}
return;
var y = 1;
}
function foo() {
var x, y;
if (false) {
x = 1;
}
return;
y = 1;
}
请注意,声明的分配部分未被提升。 仅提升名称。函数声明不是这种情况,整个函数体也将被提升。但请记住,声明函数有两种常用方法。请考虑以下JavaScript:
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%归功于 ben cherry 。我不想在我的回答中发布此链接,因为链接可能会中断,我发现这完全提供了信息,并且必须为任何JavaScript开发人员阅读。