当然了,大叔就是举个栗子,你也别太当真啦~ 总而言之,就是说咱们在真实开发时对变量的命名肯定是有规划的,不能随意就被重新声明使用,这样会让命名空间很乱很乱滴。
你可能有想问了,这个问题要怎么解决呢?答案其实很简单,就是使用 ES6 新增的这个 let 关键字。因为 let 关键字声明的变量是不允许被重复声明,否则会报错滴。不信你也可以看看嘛:
let a = 'a' let a = 'aa' console.log(a)仅仅只是把 var 改成 let,这个结果就是报错了,报错的内容是:SyntaxError: Identifier 'a' has already been declared,大概的意思就是变量 a 已经被声明过了。
所以,你看,let 可不是仅仅那么一点点的区别呢!
不允许声明提前这会儿你是不是又想问 let 和 var 之间还有没有其他区别啊?大叔也不藏着掖着了,干脆一口气都和你说了吧!你知道使用 var 关键字声明的变量是允许声明提前的吗?啥?不知道!没事儿,这个简单,啥叫声明提前,来看段代码:
console.log(a) var a = 'a'你运行一下这段代码,看看打印的结果是啥?没错~ 结果就是 undefined。为啥不是报错呢?原因就是使用 var 关键字声明的变量允许声明提前。还是说人话吧,也就是说,上面这段代码和下面这段代码本质上是没区别的:
var a console.log(a) a = 'a'这样婶儿写你可能就明白了为啥打印的结果是 undefined 而不是报错了吧!但是,嘿嘿~ 咱们又得唠扯唠扯 let 了,因为 let 声明的变量就不允许声明提前。不信的话还是给你看段代码先:
console.log(a) let a = 'a'这段代码运行之后打印的结果就是报错,报错的内容是:ReferenceError: Cannot access 'c' before initialization,大概的意思就是无法在声明变量 c 之前访问变量 c。
暂时性死区(TDZ)let 是不是挺屌的吧?!那你想不想知道 let 声明的变量又为啥不允许声明提前呢?嘿嘿~ 这是因为使用 let 声明变量的过程中存在一个叫做暂时性死区(Temporal dead zone,简称 TDZ)的概念。
是不是觉得挺高深的?哈哈~ 其实没啥高深的,大叔就给你唠扯明白这个事儿。规矩不变,咱还是先看段代码再说:
if (true) { console.log(a) let a; console.log(a) a = "a"; console.log(a) }大叔想先问问你这段代码里面三处打印的结果分别是啥?你得认真的寻思寻思哈~ 这可都是大叔刚和你唠过的内容。
第一处打印的结果是报错,报错内容就是 ReferenceError: Cannot access 'c' before initialization
第二处打印的结果是 undefined
第三处打印的结果是 b
对于这样的结果,大叔估计你应该会明白,毕竟都是刚唠过的内容。接下来,你得认真的看了,因为大叔要和你来唠扯有关暂时性死区的概念了~
所谓的暂时性死区,就是说使用 let 关键字声明的变量直到执行定义语句时才会被初始化。也就是说,从代码从顶部开始执行直到变量的定义语句执行,这个过程中这个变量都是不能被访问的,而这个过程就被叫做暂时性死区。
具体到上面这段代码的话,实际上暂时性死区的开始和结束位置就像下面这段代码标注的一样婶儿:
if (true) { // 暂时性死区开始 console.log(a); // 报错,ReferenceError: Cannot access 'a' before initialization let a; // 暂时性死区结束 console.log(a); // 输出undefined a = "a"; console.log(a); // 输出a }捞到这会儿,大叔相信你应该可以明白啥子是暂时性死区了。其实啊,一些新的概念也没啥难理解的,主要是你理解的角度和方式的问题。
typeof 运算符也不再安全总体上来说,let 关键字要比 var 关键字严格了许多,导致我们开发时遇到的问题相应会减少许多。但 let 就没有任何问题了吗?答案显然不是滴,大叔一直信奉一句话:任何技术都没有最优,只有最适合。
ES6 新增的 let 关键字也是如此,就比方说刚才咱们捞的暂时性死区的内容,其实就有问题。啥问题呢?你还记得 JS 里面有个运算符叫做 typeof 吧,就是用来判断原始数据类型的。这个运算符在 let 出现之前相对是比较安全的,说白了就是不容易报错。但在 let 出现之后就不一定了,比方说如果你把它用在刚才说的暂时性死区里面,它就会报错了:
if (true) { console.log(typeof c) let c; }这段代码最终打印的结果同样是报错,报错内容同样是:ReferenceError: Cannot access 'c' before initialization。
块级作用域关于 let 关键字咱们捞到这会儿,其实基本上已经唠完了。但是,但可是,可但是~ 嘿嘿~ let 还有一个最重要的特性大叔还没和你唠呢,这重量级的都得最后出场不是?!