首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >块作用域函数ECMAScript 6奇怪行为

块作用域函数ECMAScript 6奇怪行为
EN

Stack Overflow用户
提问于 2017-06-09 06:22:08
回答 3查看 435关注 0票数 3

我正在阅读ECMA6中的新特性。其中一个新特性是块作用域函数。这意味着我们可以对不同块中的函数使用相同的名称。如下面的代码所示,block1 foo()记录1,类似地,block2 foo()日志2和block0 foo() or global scope日志4,这是预期的结果。但我无法理解的是,为什么最后一个console.log(foo())记录的是1而不是4,因为它在block0 or global scope下面,而不是日志1,即block1 foo()

代码语言:javascript
复制
//block0
function foo () { return 4 }
console.log(foo());//will log 4
{
		//block1
    function foo () { return 1 }
    console.log(foo());//will log 1
    {
    //block2
        function foo () { return 2 }//a block level function
        console.log(foo());//will log 2
    }
    console.log(foo());//will again log 1
}
console.log(foo());//should log 4 but logs 1 why?

现在,如果我将上面的代码封装到另一个块中,它就会像预期的那样工作。这让我有点困惑。究竟是什么导致了这一现象?

代码语言:javascript
复制
{//block0
function foo () { return 4 }
console.log(foo());//will log 4
{
		//block1
    function foo () { return 1 }
    console.log(foo());//will log 1
    {
    //block2
        function foo () { return 2 }
        console.log(foo());//will log 2
    }
    console.log(foo());//will again log 1
}
console.log(foo());//will log 4 but 
}

EN

回答 3

Stack Overflow用户

发布于 2017-06-09 07:30:04

您需要确保启用严格模式。由于默认情况下它是在模块中启用的,所以我猜您的示例代码没有显示这一点。康阿克斯兼容表显示了一个适当的测试。

代码语言:javascript
复制
"use strict";
//block0
function foo () { return 4 }
console.log(foo());//will log 4
{
		//block1
    function foo () { return 1 }
    console.log(foo());//will log 1
    {
    //block2
        function foo () { return 2 }//a block level function
        console.log(foo());//will log 2
    }
    console.log(foo());//will again log 1
}
console.log(foo());//logs 4

票数 2
EN

Stack Overflow用户

发布于 2017-06-09 07:28:34

深度解释的完全修正的答案

首先要做的是:出现问题是因为您没有使用use strict模式。在这种情况下,strictnon-strict模式有什么不同?区别在于处理简单块范围的方式。

在这两种模式中,括号块都会创建一个作用域。该范围内的声明可以在作用域中本身和进一步封闭的作用域中查看。

代码语言:javascript
复制
{ // level 1 scope
  function asdf() {alert("asdf");}
  { // level 2 scope
    asdf(); // Yay I can use it!
  }
}

然而,,在ES5和ES6 non strict中,简单的块作用域并不被视为真正的封闭作用域。在一个简单的块范围内的声明会一直被提升到他们能找到的第一个真正的包围作用域。在这些情况下,真正的包围作用域要么是函数的作用域,要么是全局范围。

non strict模式下,上述示例等价于以下内容:

代码语言:javascript
复制
var asdf0 = undefined; // Haha! The declaration has been hoisted up to the global scope!
{ // level 1 scope
  function asdf1() {alert("asdf");}
  asdf0 = asdf1; // The definition is ready and will be assigned to its declaration
  { // level 2 scope
    asdf1(); // Yay I can use it!
  }
}
asdf0(); // Damn! I have access outside of the block scope due to hoisting! Should have used strict mode...

但是,如果我们将前面的逻辑封装到一个function中,那么就不会提升到全局范围,只会提升到函数的作用域。

代码语言:javascript
复制
function scopeBlocker() {
  var asdf0 = undefined;
  ...
  ...
}
asdf0(); // Exception! Wasn't hoisted all the way up to the global scope!

现在来看一下您的示例,因为您是而不是使用strict mode,所以您掉进了旧块范围的陷阱中。在第一次尝试中,第一个块作用域中的第二个声明一直挂起到它的封闭范围,并替换了第一个foo声明。现在,由于吊装只发生一次,下面的声明是,而不是,因此没有替换任何东西。在第二种情况下,添加顶级块作用域迫使将第一个foo声明悬挂到全局封闭范围,因此第二个foo声明现在是未悬挂的,因为foo名称已经悬挂。

这的确是一种奇怪的行为,但我相信这就是这里正在发生的事情。

票数 1
EN

Stack Overflow用户

发布于 2017-06-09 06:34:27

我认为这取决于您在哪里运行代码。也许这个特性现在还不受支持。您的代码片段记录了4、1、2、2、2 (Firefox浏览器)。

逻辑上,您的代码应该如您所说的那样进行记录。

你到底在哪里测试代码?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44450644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档