JavaScript高级程序设计第四版(let 声明、临时死区、全局声明、条件声明)

let 声明

let的操作与var几乎相同的,但是有一些重要的区别。最需要注意的是: let是块作用域,而var是函数作用域的。

if (true) {
   var name = 'Matt';
   console.log(name); //Matt
}
console.log(name); //Matt
if (true) {
    let age = 26;
    console.log(age); //26
}
console.log(age); //Uncaught ReferenceError: age is not defined

这里的age变量无法在if块外引用,因为其范围并没有扩展到if块之外。块级作用域 严格来说是功能作用域的子集,因此任何作用域限制适用于var声明也都适用于let声明。
let声明还不允许在块范围内进行多余的声明。这样做的话会导致报错:
var name;
var name;
let age;
let age; // SyntaxError; identifier 'age' has already been declared

当然,JavaScript引擎会跟踪用于变量声明的标识符以及 块作用域在内部声明,因此使用相同标识符的嵌套的行为与预期的结果相同 ,不会发生错误,因为没有重新声明:
var name = 'Nicholas';
console.log(name); // 'Nicholas'
if (true) {
  var name = 'Matt';
  console.log(name); // 'Matt'
}
let age = 30;
console.log(age); // 30
if (true) {
   let age = 26;
   console.log(age); // 26
}

声明冗余错误不是有序函数混入var,是不受影响的,不同的关键字不声明不同类型的变量, 它们只是指定变量如何存在于相关范围内。
var name;
let name; // SyntaxError
let age;
var age; // SyntaxError


临时死区

let区别于var的另一个重要表现是,let声明不能以假定提升的方式使用:
// name变量被提升
console.log(name); // Matt
var name = 'Matt';
// age变量并没有被提升
console.log(age); // ReferenceError: Cannot access 'age' before initialization
let age = 26;

解析代码时,JavaScript引擎仍然会知道稍后出现的let声明 在一个块中,但是在实际声明之前将无法以任何方式引用这些变量 发生。 在声明之前发生的执行段称为“临时死区(TDZ)”,并且任何对这些变量的引用尝试都将引发ReferenceError


全局声明

与var关键字不同,使用全局上下文中的 let 声明变量时,变量不会像使用var那样添加到window对象中:
    var name = 'Matt';
    console.log(window.name); // 'Matt'
    let age = 26;
    console.log(window.age); // undefined
但是,let声明仍存在于全局块作用域内,一直持续到页面销毁之前。 因此,为了避免引发SyntaxError, 您必须确保不会重复声明。


条件声明

使用 var 声明变量时,由于变量提升,JavaScript 引擎将 顺利地将冗余声明合并为范围顶部的单个声明。由于 let声明的作用域是块,因此无法检查let变量是否已经 声明,所以只有在没有声明的情况下才有条件地声明它。
<\script>
var name = 'Nicholas';
let age = 26;
// 假设此脚本不确定页面中已经声明了什么
// 它将假定尚未声明变量。
var name = 'Matt';
// 这里没有问题,因为这将作为单个声明提升进行处理。
// 无需检查它是否先前已声明。
let age = 36;
// 当已经声明"age"时,这将引发错误。
<\/script>
使用try / catch语句或typeof运算符并不能解决问题,因为条件块中的let声明将作用于该块。
let name = 'Nicholas';
let age = 36;
// 假设此脚本不确定页面中已经声明了什么
// 它将假定尚未声明变量。
if (typeof name !== 'undefined') {
let name;
}
// 'name' 限于if {}块范围
// 因此,此分配将作为全局分配
name = 'Matt';
try (age) {
// 如果未声明gae,则将引发错误
}
catch(error) {
let age;
}
// 'age' 仅限于catch {}块范围,
// 因此,此分配将作为全局分配
age = 26;因此,您不能依赖这一种 ES6 声明关键字的条件声明模式。注意:不能使用let 条件声明是一件好事,因为条件声明是代码库中的不良模式。它使它更难理解程序流。如果你发现自己有这样写,你可以试着去用更好的方式去编写。

如果发现有那些地方不对,请积极指出,以便更改

 仅供个人学习之用,切勿进行商业用途,转裁请注明出处,否则追求相关法律责任。

猜你喜欢

转载自www.cnblogs.com/yang656/p/12382296.html