【问题标题】:Name resolution in Javascript? [duplicate]Javascript中的名称解析? [复制]
【发布时间】:2012-08-30 12:05:58
【问题描述】:

我正在阅读此article,我有一些问题请:

考虑到这段代码:

1:   var a = 1;
2:   function b () {
3:       a = 10;
4:       return;
5:       function a() {}
6:   }
7:   b();
8:   alert(a);

这会提醒 1。(我的问题是为什么?)

文章陈述了它与名称解析的相关性。

名称解析(根据文章)按此顺序确定:

1. Internal mechanisms of language: for example, in all scopes are available “this” and “arguments”.
2. Formal parameters: the functions can be named as the formal parameters, which scope is limited to the function body.
3. Function declarations: declared in the form of function foo() {}.
4. Variable declarations: for example, var foo;.

第 3 行假设更改全局 a 的值。 但是函数 a(){...} 优先于内部声明(如果我理解正确的话) 这就是为什么警报 1

附言如果我删除第 5 行,它会提醒 10。

一般来说,如果一个名字已经被定义,它就永远不会被重新定义 由另一个具有相同名称的实体。那就是函数声明 具有相同的变量声明的优先级 姓名。但这并不意味着变量赋值 不替换函数,只是忽略它的定义。

我不明白那部分:

但这并不意味着变量赋值 不替换函数

请回答两个问题:

  • 我是否正确理解了提醒1的原因

  • 以上行是什么意思? (被误解的部分)

谢谢。

【问题讨论】:

  • 我知道这不是一个答案,但我们不能只给函数和变量起正确的名字,而不用担心在虚构的情况下会发生什么吗?
  • @jbabey 有些人喜欢更深入地研究事物,以了解它们在不同场景中的工作方式。这是其中之一。名称在这里并不重要。这只是一个例子。
  • 我很抱歉,Royi,发布了同一篇文章。感谢您让我注意到这一点。

标签: javascript hoisting


【解决方案1】:

我是否正确理解了提醒 1 的原因

是的

“但这并不意味着变量赋值不替换函数”
上面的线是什么意思? (被误解的部分)

这只是意味着虽然名称为a 的函数已定义,但a = 10 仍将被执行,即在那一行之后a 不再指代函数而是指10

我假设他们想稍微放宽前面的语句,避免人们错误地认为因为函数声明首先执行,所以分配不会再发生。


函数和变量声明被提升到作用域的顶部。所以代码相当于:

1:   var a = 1;
2:   function b () {
3:       function a() {}
4:       a = 10;
5:       return;
6:   }
7:   b();
8:   alert(a);

function a() {...} 在本地范围内创建符号(变量)a,其值与函数完全相同。下一行 a = 10; 然后为该符号分配一个新值,即一个数字。

var a = 1;
function b () {
     function a() {} // creates a new local symbol `a`, shadowing the outer `a`
     // until here, `a` refers to the function created 
     // created by the above declaration
     a = 10; // now a new value is assigned to the local symbol/variable `a`
     // from here on, `a` is `10`, not a function
     return;
}
b();
alert(a);

【讨论】:

  • ,将 #3 更改为 window.a = 10; 将警告 10 ,那么这里发生了什么? jsfiddle.net/rlemon/KSUsF
  • 好吧,如果你在全局范围内运行代码,那么var a = 1;会创建一个全局变量,window.a = 10显式10赋值给全局变量a .
  • 第 4 行的 a 不是和全局的一样吗?
  • 不...我以为你知道这个...a指的是由function a(){...}创建的本地范围内的符号。
  • 所以 function a() {} 的行为类似于 var a; (创建本地范围 a
【解决方案2】:
var a = 1;
function b () {
    var a = 10;
}
b();
alert(a);

上面的例子对你有意义吗?是的?好,那你就明白本地和全局范围的区别了……

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

这个例子对你有意义吗?是的?然后你就明白了,变量在函数中声明的位置无关紧要,总是在第一次进入函数时声明。

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

现在,这个例子有意义吗?是的?然后你就理解了动态类型。一个变量可以被赋予一个函数作为一个值,然后可以被一个整数覆盖,比如 10。

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

现在你的例子应该是有意义的,因为我们只是改变了我们声明 a 的方式,但它是一样的。

【讨论】:

  • “一个变量可以被赋予一个函数作为一个值,然后可以被一个整数覆盖”——是的,但这里不是这样。函数赋值永远不会执行,因为它遵循return 语句。只有var a; 被提升。
  • @pimvdb 函数声明与它们的主体一起被提升 - 它不会被拆分成单独的声明/赋值语句。
  • 我以为你用那句话指的是var a = function() { };。请注意与函数声明的区别。
  • @pimvdb 是正确的,我的错。变量 a 被定义,赋值为 10,然后被函数值覆盖。我想说明一点,a 在第一个站点与什么相关联并不重要,因为它可以被任何值覆盖。我想我在这里的例子不是最好的,好的。
  • @jbabey 我不明白。该函数的优先级高于 var a ,所以如果它有优先级,为什么 var a 仍然执行?
【解决方案3】:

根据我对提升的理解,变量声明和函数声明都是提升的。因此,这就是正在发生的事情:

var a; // a is declared (hoisted)
function b () { // function declaration (hoisted)
    function a () {} // function declaration (hoisted)
    a = 10; // an assignment to the local a that was hoisted, not the outer a
    return;
}
a = 1; // initialization (not hoisted)
b(); // hoist inside b's scope causes an inner a to be modified
alert(a); // alerts 1 since the outer a was never modified

【讨论】:

  • 不,函数是真的创建的:jsfiddle.net/mwLVD。赋值只是用另一个值覆盖现有符号。
  • @FelixKling 函数a 已创建?我认为只有名称被提升,而不是分配(函数不会发生这种情况吗?)
  • 但这不是赋值,而是函数声明function a() {...}a = function() {...} 不同(这正是不同之处)。
  • @FelixKling 你是对的;很高兴知道! “函数声明('bar' 和函数体被提升)”source
  • @FelixKling 我已经编辑了我的答案以反映这些新信息。再次感谢。
猜你喜欢
  • 2017-12-04
  • 2012-03-22
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 2010-12-27
相关资源
最近更新 更多