后台JS由于语言设计缺陷(没有足够的时间限制?),其中有一些神奇的功能。初学者遇到可能会一脸黑问号。介绍的是功能之一:Hoisting。如果你是JS新手,有时候你会遇到undefined或ReferenceErrors错误,而声明提升可能就是罪魁祸首。声明提升通常被解释为将变量和函数放在文件的顶部,表面上并非如此。编译阶段当JS引擎开始解析我们的脚本时,它做的第一件事就是为我们代码中的变量设置内存。这个阶段的代码还没有运行起来,只是在为后面的代码的执行做准备。这个阶段就是编译阶段。此阶段的一部分是查找所有声明并将它们与适当的范围相关联(我们将在下一次讨论范围)。例如vara=2;JS引擎会将其视为两个声明:vara;和一个=2;。第一条定义语句在编译阶段进行,第二条赋值语句留在原地等待执行阶段。在编译阶段,函数声明和变量声明的存储方式不同。函数声明的存储方式函数声明的存储是存储整个函数在内存中的引用。(注意函数声明和函数表达式的区别)在下面的代码中,我们先看函数sum的声明:let和const声明的变量存储方式不同。ES6引入了两个新关键字:let和const。对于用这两个关键字定义的变量,存储的值是未初始化的。用var声明的变量的存储方式默认为undefined值。执行阶段现在编译阶段已经完成,是时候让JS引擎执行代码了。我们在文件顶部添加三个console.log语句。提前调用函数如上所述,由于函数声明在编译阶段存储了整个函数的引用,因此甚至可以在函数声明之前调用函数。预先使用var定义的变量如果我们预先使用变量city,那么打印出var关键字定义的默认值会是undefined。大多数时候,这种行为令人困惑,因为您不希望它的值是未定义的。const和let定义的变量是为了解决var的问题提前使用的,所以才有了const和let。当我们访问他们预先定义的变量的默认值未初始化时,就会抛出ReferenceError。这种行为有一个霸气的名字:时间死区(TemporalDeadZone),即在初始化之前你不能访问这个变量。继续执行赋值操作当JS引擎继续解释代码时,当解释到某行的赋值语句时,会用代码中定义的值覆盖内存中的值。(上图中的数字应该是7哈~)综上所述,我们回顾一下:函数和变量在编译阶段会将声明部分存放在内存中,也就是声明提升(还涉及到执行上下文的概念,下一篇我们会讲)函数声明存放的是整个函数的引用,var声明的变量存放的默认值是undefined,let和const声明的变量默认值是未初始化的。本文翻译自作者LydiaHallie的系列文章。部分内容进行了详细说明。下面还有三篇文章。欢迎订阅公众号关注更新:DynamicGraphicsJavaScript:Hoisting【本文】DynamicGraphicsJS之:作用域链(ScopeChain)JS之动态:事件循环(EventLoop)之动态JS之动态:JavaScriptEngine之动态JS:PrototypeInheritanceReferenceJavaScriptVisualizedHoistingTemporalDeadZone你不知道的JavaScriptroll
