译:用let 和 const 来指导JavaScript 的变量提升

发布时间:2019-08-19 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了译:用let 和 const 来指导JavaScript 的变量提升脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

图片描述

最近在Medium上看到一篇关于“变量提升”的文章,原文在此:《A guide to JavaScript variable hoisting with let and const》。为了培养自己看英文文档习惯且看懂的需要,就翻译一下。谈不上精确,欢迎指正。

对于刚入门的JavaScript开发者时常难以理解“变量/方法”提升(hoisting)的独特行为。
接下来我们要谈论varletconst声明,那么先了解变量提升就显得更为重要了。那就开始吧。

图片描述

@H_304_16@什么是变量提升?

JavaScript引擎用“var”处理所有变量声明,不管在哪里声明,最后都会在函数作用域顶端(如果在函数内部声明)或则在全局作用域顶端(在函数外部声明)。这就是“提升”。
因此变量实际上可能在声明它之前就已经被引擎获得了。
图片描述

在实际操作中看看效果..

// OUTPUT : undefined
console.LOG(Shape);
VAR shaPE = square;
// OUTPUT : square
console.log(shape);

如果你来自c语言,你认为在第一个console.log那里就会抛出变量未定义的错误。但JavaScript解释器预感和“提升”所有变量声明到作用域顶端,并且在那进行初始化。
下面演示实际发生了什么:

//declaration getting hoisted at the top
var shape;
// OUTPUT : undefined
console.log(shape);
shape = square;
// OUTPUT : square
console.log(shape);

另一个例子是用函数作用域来更清楚的展示:

 function getShape(condITion) {
    // shape exists here with a value of undefined
    // OUTPUT : undefined
    console.log(shape);
    if (condition) {
        var shape = square;
        // some other code
        return shape;
    } else {
        // shape exists here with a value of undefined
        return false;
    }
}

上面的例子可以看出shape声明被提升到了“getShape”函数作用域的顶端。这是因为“if/else” 不能像其他语言那样,创建局部作用域。在JavaScript里,函数作用域实际上就是局部作用域了。因此,“shape”可以在if块之外,函数作用域内任意访问,且值为“undefined”。

JavaScript的这个默认行为,既是优点,又是缺点。没有完全掌握的话,会给我们的代码带来细微且危险的bugs。

进入块级作用域!

译:用let 和 const 来指导JavaScript 的变量提升


ES6 引入了块级作用域,这让开发者对变量有了更多的控制,且让变量有灵活的生命周期。
块级声明在块级/词法作用域里面声明,他们在“{}”中被创建。

let声明

let”语法跟“var”相似,只是用“let”标识符来替换“var”标识符进行变量声明,其作用域范围仅仅在声明的那个代码块。
let声明放在块的顶端,因此只能在那个块级作用域中访问。
举例:

function getShape(condition) {
  // shape doesn't exist here
  // console.log(shape); ReferenceError: shape is not defined
  if (condition) {
    let shape = square;
    // some other code
    return shape;
  } else {
    // shape doesn't exist here as well
    return false;
  }
}

注意shape只存在if块中,当在if块外面访问时会抛出一个错误,而不是象我们之前用var声明那样输出“undefined”。
提示:在同一个作用域内,如果已经使用var标识符声明了变量,同时又用let标识符声明同名变量时会抛出错误。
但是,如果在let声明的变量作用域外,声明同名变量是不会报错的。(这种情况也同样适用于我们即将谈论的const声明。)
举例:

var shape = square;

let shape = rectangle;
// SyntaxError: Identifier 'shape' has already been declared

var shape = square;
if (condition) {
  // doesn't throw an error
  let shape = rectangle;
  // more code 
}
// No error

const声明

const声明语法与let和var相似,生命周期与let相同,但你还要注意一些规则。
用const声明的变量将像常量看待,因此它们的值在定义后是不可以修改的。由于这样,每个const变量都必须在声明的同时进行初始化
举例:

// valid 
const shape = triangle;
// syntax error: missing initialization
const color;
// TypeError: Assignment to constant variable
shape = square;

然而,这个规则在声明对象时有点不同。对象属性的值可以被修改!

 const shape = {
    name: triangle,
    sides: 3
}
// WORKS
shape.name = square;
shape.sides = 4;
// SyntaxError: Invalid shorthand PRoperty initializer
shape = {
    name: hexagon,
    sides: 6
}

在上面的例子中,我们可以看到shape对象属性的值可以被修改,因为我们只改变shape包含的,而不是它本身。
我们可以总结说,const可以止整个绑定的修改,而不是绑定的值。
提示:属性可以改变。所以对于真正不可变的,请使用Immutable.jsMori

暂时性死区

我们都知道,如果我们在使用let,const声明定义的变量之前就使用这些变量,会抛出ReferenceError错误。 在进入作用域和不能访问的这段时间,我们称为暂时性死区。
提示:“暂时性死区”不是ECMAScript规范里的正式定义,它只是在程序员中广为流行而已。

译:用let 和 const 来指导JavaScript 的变量提升

我个人推荐总是使用const,因为它不容易出错。我还没遇到需要使用var的情况。
作为基本规则,只在循环计数器中,或则你真的需要给变量从新赋值时用let。其他地方,用const。我已经放弃使用循环,转而选择使用filter,map,reduce等方法。你也应该如此。

后记,此作者还有一篇关于方法提升的文章,到时候在搬来。

脚本宝典总结

以上是脚本宝典为你收集整理的译:用let 和 const 来指导JavaScript 的变量提升全部内容,希望文章能够帮你解决译:用let 和 const 来指导JavaScript 的变量提升所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。