作为一个JS初学者,我一直是对ES6各种奇妙的语法带有一丝敬畏的.从var-let,promise,解构,到各种神奇的const骚操作,一直让我感觉ES6用的好的人似乎代码中包含着魔力.
今天在看知乎的时候,我发现了方方提的这样一个问题.
https://www.zhihu.com/question/62966713
x
lex x=x
x
let x
第一个第二个的报错自然好理解,不用多废话.但是第三个和第四个就比较诡异了:如果我调用x,那么会提示x未被定义.但是当我想定义x的时候,x又是已经被声明的?
我发现以我的知识无法理解这个问题.
于是看了一下底下的回答:
贺老的回答已经指出了问题的关键,但是对于我来说,还是理解的比较困难.
然后看了孙北吉 的回答,感觉自己又懂了一些.最后看了方方的博客,感觉自己似乎还是不太懂.于是尝试自己解释并总结一下.
问题的本质就是JS 变量的「创建create、初始化initialize 和赋值assign」.
在第一个报错直接输入x中,JS做了这样的操作:
在当前环境中进行查找x.
因为是全局环境 ,直接抛出一个 ReferenceError,提示x不存在.
在第二个报错lex x=x中:
lex x=x是一个RHS查询,它会直接进行值的查找并通知引擎做这些事:
1. 创建变量.
2. 开始执行代码(到现在为止,还未初始化)
3. 将x进行初始化为undefined.(这个操作并不是赋值,仅仅是初始化)
4. 执行RHS操作将x赋值给x.(这才是赋值操作)
因为我们的初始化语句与赋值语句是同一句,所以我们的let x=x同时执行了3\4步的操作.但是这里就出现了一个问题,这一句话是错的.在报错的同时,第三步已经执行完成了,而第四步就没有办法进行,在报错的同时也取消掉了第三步进行的对x的初始化.也就是说这个值已经进行了变量创建,但是并未初始化.所以:
在第三个报错x中:
这个变量x在当前的环境中已经存在(已经被创建过),但是事实上这个变量并未进行初始化,也就无法进行各种操作以及访问了.此时就会抛出一个Reference Error.
在第四个报错let x中:
在此处我们尝试着进行了let x,实际上执行的就是第二个报错的第一步-创建变量.但是变量已经被创建,所以会提示变量已存在.就这样,我们得到了一个已经被创建但是并未被声明且无法被访问的变量.
这就是我的理解,如果有错误,还请看到这里的你指正.谢谢.
So.Because JavaScript.