"use strict"在函数作用域中无法阻止变量提升

10

我的问题在这里。我正在学习JavaScript,但编程并不陌生。 我理解变量提升,但是在严格模式下,当6被分配给未声明的变量a或document.getElement...被分配给x时,它不应该产生错误并被捕获吗?所以我的判断是变量提升仍在继续...我不喜欢这种情况,并想通过使用严格模式来摆脱它。 我的浏览器是Chrome版本42.0.2311.152 m。

function strictMode(){
    'use strict';
    try {
        x = 6;
        document.getElementById('hoisting').innerHTML = x;
        var x;
     }
     catch(err) {
                    document.getElementById('error_report').innerHTML = 
                        "There was an error that occured (Were in Strict Mode)" +
                            " " + err.message;
               }
}

1
我认为严格模式并不打算移除变量提升。 - GillesC
我读到了它确实如此,这就是为什么我提出了这个问题...我从各种网站上读到了这个。 - Zach Hutchins
2个回答

15
变量声明(例如var x;)在编写它们的整个作用域内都是有效的,即使你在赋值之后声明也是如此。这就是所谓的变量提升("hoisting"): var x;被提升到作用域的开头,并且赋值x = 6;很好,因为x在该作用域中已经声明过了。 严格模式不会改变任何东西。如果你完全省略了var x;的声明,则会抛出一个错误;而没有严格模式,变量的作用域隐式地成为全局作用域。
在ES2015(又名ES6)中,可以通过使用let关键字而避免变量提升。(另一个区别是使用let声明的变量仅在包围块中本地化,而不是整个函数。)

关于隐式全局作用域的好笔记,传统上,在函数作用域中声明的任何内容仅在函数本身的持续时间内可用和“存活”。您是说严格模式是将作用域返回到传统方式的唯一方法吗? - Zach Hutchins
只要你勤奋地编写var声明,严格模式就没有任何区别。变量仍然被限定在它们声明的块范围内,即使没有启用严格模式。严格模式只是为了在你“忘记”声明变量时捕获错误。 - Thomas
还要注意,“存在”和“作用域”的概念是完全不同的。例如,如果我这样写:function foo() { var x = {}; return x; },那么x只在foo函数内部有效,但它的值可能因调用方对它的操作而“存在”更长的时间。 - Thomas

1

在学习javascript时,你必须学会使用良好的编程实践来对抗一些奇怪的允许的行为(分号就是一个很好的例子)。在提升变量方面,通常最好在其被提升到的作用域顶部声明变量。正如已经提到的,严格模式并不是万能药,不能强制执行这一点。


谢谢,我更喜欢正式的编程方式和老方法。我读到 strict 会关闭提升,因此我的测试...只是让我感到困扰的是 hoisting 没有像其他人说的那样被关闭。 - Zach Hutchins
我认为混淆可能来自于事实,就像@Thomas指出的那样,严格模式确实要求您声明变量。 - aw04

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接