-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript Hoisting(提升) #143
Comments
考验基础的面试题 function Foo () {
getName = function () { alert(1) }
return this
}
Foo.getName = function () { alert(2) }
Foo.prototype.getName = function () { alert(3) }
var getName = function () { alert(4) }
function getName () { alert(5) }
Foo.getName(); // code1
getName(); // code2
Foo().getName(); // code3
getName(); // code4
new Foo.getName(); // code5
new Foo().getName(); // code6
new new Foo().getName(); // code7 输出结果是啥? |
全局整体分析:
|
|
|
|
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
英文 Hoisting ['hɔɪstɪŋ],直译过来是
提升
的意思,也交预处理。 在ES6
之前的JavaScript
开发中,我们经常遇到这种Hoisting
的场景,但这种设计是很低劣的,被很多语言专家认为是JavaScript
最大的设计败笔之一,本文主要来聊一聊这种Hoisting
.造成这种
Hoisting
的原因,大概是JavaScript
的作用域规则的确定阶段造成的,我们在《JavaScript 执行上下文和执行上下文栈(Execution Context Stack简称ECS)》,一文中提到JavaScript
代码的整个执行过程,分为两个阶段:那么在编辑阶段确定了全局变量和所有的函数的作用域规则,具体的操作是将所有声明(
Declaration
)的变量和声明的函数提升到对应作用域的顶部,即:很多网络资料把这叫做
变量提升
,其实只说对了一半,严谨的叫法应该是声明提升
一、变量声明提升(variable declaration hoisting)
对于上面的例子,先打印
blog
变量,再使用关键字var
去声明变量blog
,在浏览器的Console
下运行,我们发现并没有报错,而是输出undefined
.那为什么会这样呢?因为浏览器在编译阶段做了
Hoisting
的动作处理,Hoisting
后的代码是这样的:二、函数声明提升(function declaration hoisting)
函数声明提升指的是
整个函数体的提升
在
JavaScript
语言中,创建函数有两种常见的方式: 函数声明和函数表达式,在这个两种方式中,只有函数声明具有整体提升特性
上面的代码,
console.log(show);
打印出整个函数,证明函数声明提升指的是整个函数体的提升
,函数show()
的执行晚于其定义。上面的代码是函数表达式,不具有
整体提升特性
三、函数声明提升优于变量声明提升
相比与变量声明提升,函数声明提升会优先进行, 因为JavaScript中的函数是一等公民,函数声明的优先级最高,会被提升至当前作用域最顶端。
上面的代码,
show
函数和 变量show
, 名称相同,那么他们两个都应该提升了,按照变量提升
去理解第一行应该打印出undefined
, 但是这里却打印出了show
函数体,由此证明函数声明提升优于变量声明提升
,所以上面的代码经过编译阶段后是这样的:思考一下,下面的代码输出情况
四、Hoisting 是 JavaScript 语言最大的设计败笔之一
通过前面几段代码的解读,即使是
JavaScript
高手也有种读绕口令的困惑,JavaScript
的这种提升行为(behavior
)给程序开发者造成了很大的confusion
(困惑)和很烂的开发体验,被很多JavaScript
专家认为是JavaScript
语言最大的设计败笔之一。为了改善这种
Hoisting
现象,在很多公司或组织内部的JavaScript
规范中(英文叫JavaScript Standard Style
),规定变量必须先声明后使用。但规范并不能解决根本问题,幸运的是,这种
Hoisting
在ES6
中得到巨大的改善。在ES6
中我们不再提倡使用var
去声明变量,而是提倡let
和const
去声明变量,ES6
通过暂时性死区和let
、const
的使用,防止变量在声明前就去使用从而导致意料之外的行为。无论是流行的
JavaScript
规范还是ES6
新增的let
和const
,都是为了解决这种设计败笔,业界一致认为:变量应该是先声明后使用, 这样的设计是为了让大家养成良好的编程习惯,提高程序的可读性和可维护性。Reference
The text was updated successfully, but these errors were encountered: