【问题标题】:How the below JavaScript Scope works [duplicate]以下 JavaScript 范围如何工作 [重复]
【发布时间】:2015-03-19 13:15:23
【问题描述】:

我正在阅读 JavaScript scopesHoisting。我看到下面的示例让我产生了一些疑问。所以,我想知道它是如何工作的。

var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

代码会提醒1!但是如果我们去掉 "function a(){}" 部分,代码会提示 10。

那么,它是如何工作的! “函数 a(){}”在这里做什么以及它如何影响范围。

我也看不懂这段代码中空“return;”的含义。

那么,这段代码如何依赖 JavaScript 作用域工作?

【问题讨论】:

  • 阅读“吊装”。
  • 这被称为“提升”,这是一篇解释它并使用该确切代码的文章! adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
  • 是的。我读过关于吊装的书,但我仍然有疑问。基于提升函数声明和变量声明总是被 JavaScript 解释器不可见地移动(“提升”)到其包含范围的顶部。所以,我还是不明白它是如何影响这段代码的。
  • 是的。我的疑问正是从您发送的链接中提出的!
  • @GrijeshChauhan 这个问题删除了第 5 行。链接的问题没有考虑这种变化。

标签: javascript


【解决方案1】:

首先,“空”return; 语句在该点简单地退出函数,返回 undefined。相当于return undefined;

简单的情况,如果去掉function a(){}部分,就是b()函数把全局变量a改成10,那么当你在运行后提醒a的值b() 函数是 10。如果没有那个内部函数,所有对a 的引用都意味着全局变量。

但是 function a(){} 部分,该函数被声明为inside b()。它是b() 的本地地址。那么你有两个不同的as:全局变量和b() 中的局部变量。无论包含函数的哪个位置出现另一个函数语句,JS 编译器都会将其视为位于函数的顶部。因此,即使 function a(){} 行实际上位于包含 b() 函数的末尾,代码运行时会发生以下情况:

var a = 1;              // declare a global variable a
function b() {
    function a() {}     // declare a local function a
    a = 10;             // update local a to be 10 instead of a function
    return;
}
b();
alert(a);  // show value of global a, which is still 1

【讨论】:

  • 另一种表达第 3 行的方式,这可能更好地说明发生了什么:var a = function a() {};(在这种情况下,任何一种方式都是完全相同的)
  • JS解释器/编译器这样做有明确的原因吗?
  • @Traubenfuchs - 因为这就是语言规范所说的。 (编译器并没有真正向上移动变量声明,它编译包含声明的函数,然后运行该函数,但从概念上讲,“提升”/移动的想法具有相同的结果,大多数人似乎发现它更容易可视化。 )
  • 感谢您的回答。这个答案是帮助我理解代码功能的答案..
  • @Ajedi32 - 不,函数语句被“提升”包括定义。因此,插入console.log(a) 作为b() 的第一行 记录函数,而a 成为undefined。 (用var 声明的变量的值不会被提升,所以如果你有var a = function... 那么 a 如果在该行之前记录,则undefined 将是undefined,但函数语句 是一种特殊情况。)
【解决方案2】:

除了nnnnnn's great answer,我还试着想象一下情况。

使用function a(){},您的代码行为如下:

scope: window                         scope: b
      |                                   |
      | var a = 1;  //window.a = 1;       |
      |                                   |
      | function b() { -----------------> |
      |                                   | function a(){} // b.a(){} (hoisted to top)
      |                                   | a = 10;        // b.a = 10;
      |                                   | return;
      | } <------------------------------ |
      |                                   |
      | b();                              |
      | alert(a);  // alert(window.a);    |

我们可以看到function a(){} 被提升到函数的顶部,因为它包含一个声明。如果我们删除function a(){},代码的行为如下:

scope: window                         scope: b
      |                                   |
      | var a = 1;  //window.a = 1;       |
      |                                   |
      | function b() { -----------------> |
      |                                   | a = 10;        // window.a = 10;
      |                                   | return;
      | } <------------------------------ |
      |                                   |
      | b();                              |
      | alert(a);  // alert(window.a);    |

【讨论】:

  • 那里的图表很好。
  • 漂亮的图表.. 完全有帮助
【解决方案3】:

您的代码在功能上与此代码相同:

var a = 1;
function b() {
    var a = function() {}
    a = 10;
    return;
}
b();
alert(a);

使用function NAME() { ... } 表示法有效地将函数声明置于当前作用域的开头,作为本地(该作用域)声明。

事实上,如果你执行

var a = 1;
var c= 2;
function b() {
    a()
    a = 10;
    return;
    function a() { alert(c) }
}
b();
alert(a);

它会输出:

2
1

我个人不使用这种符号,我总是明确地使用赋值。

jsfiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2010-12-07
    • 2010-09-16
    相关资源
    最近更新 更多