老铁们,大家好,相信还有很多朋友对于hoisting是什么意思,hoisting的意思翻译、用法、同义词、和JavaScript的相关问题不太懂,没关系,今天就由我来为大家分享分享hoisting是什么意思,hoisting的意思翻译、用法、同义词、以及JavaScript的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
1、上面这段代码在运行时会产生什么结果?
2、尽管对于有经验的程序员来说这只是小菜一碟,不过我还是顺着初学者常见的思路做一番描述:
3、在foo的函数体内,if语句将不会执行,因为!a会将变量a转变成布尔的假值,也就是false
4、跳过条件分支,alert变量a,最终的结果应该是输出1
5、嗯,看起来无懈可击的推理啊,但让人惊讶的是:答案竟然是2!为什么?
6、别着急,我会解释给你听。首先我要告诉你这不是什么错误,而是JavaScript语言解释器的一个(非官方的)特性,某人(BenCherry)把这个特性叫做:Hoisting(目前尚未有标准的翻译,比较常见的是提升)。
7、为了理解Hoisting,我们先来看一个简单的情况:
8、你是否想过,上面这句代码在运行的时候到底发生了什么?
9、你是否知道,就这句代码而言,“声明变量a”和“定义变量a”这两个说法哪一个才是正确的?
10、声明:是指你声称某样东西的存在,比如一个变量或一个函数;但你没有说明这样东西到底是什么,仅仅是告诉解释器这样东西存在而已;
11、定义:是指你指明了某样东西的具体实现,比如一个变量的值是多少,一个函数的函数体是什么,确切的表达了这样东西的意义。
12、重点来了:当你以为你只做了一件事情的时候(vara=1),实际上解释器把这件事情分解成了两个步骤,一个是声明(vara),另一个是定义(a=1)。
13、回到最开始的那个令人困惑的例子,我告诉你解释器是如何分析你的代码的:
14、如代码所示,在进入函数体后解释器声明了新的变量a,当时其值为undefined,于是if语句条件判断结果为真,接着为新的变量a赋值为2。你若不相信可以在函数体外面alert(a),然后再执行foo()对比一下结果就知道了。
15、有人可能会问了:“为什么不是在if语句内声明变量a?”
16、因为JavaScript没有块级作用域(BlockScoping),只有函数作用域(FunctionScoping),所以说不是看见一对花括号{}就代表产生了新的作用域,和C不一样!
17、当解析器读到if语句的时候,它发现此处有一个变量声明和赋值,于是解析器会将其声明提升至当前作用域的顶部(这是默认行为,并且无法更改),这个行为就叫做Hoisting。
18、懂了不代表就会用了,就拿最开始的例子来说,如果我就是想要alert(a)出那个1可咋整呢?
19、alert(a)在执行的时候,会去寻找变量a的位置,它从当前作用域开始向上(或者说向外)一直查找到顶层作用域为止,若是找不到就报undefined。
20、因为在alert(a)的同级作用域里,我们再次声明了本地变量a,所以它报2;所以我们可以把本地变量a的声明向下(或者说向内)移动,这样alert(a)就找不到它了。
21、记住:JavaScript只有函数作用域!
22、你或许在无数的JavaScript书籍和文章里读到过:“请始终保持作用域内所有变量的声明放置在作用域的顶部”,现在你应该明白为什么有此一说了吧?因为这样可以避免Hoisting特性给你带来的困扰(我不是很情愿这么说,因为Hoisting本身并没有什么错),也可以很明确的告诉所有阅读代码的人(包括你自己)在当前作用域内有哪些变量可以访问。但是,变量声明的提升并非Hoisting的全部。在JavaScript中,有四种方式可以让命名进入到作用域中(按优先级):
23、语言定义的命名:比如this或者arguments,它们在所有作用域内都有效且优先级最高,所以在任何地方你都不能把变量命名为this之类的,这样是没有意义的
24、形式参数:函数定义时声明的形式参数会作为变量被hoisting至该函数的作用域内。所以形式参数是本地的,不是外部的或者全局的。当然你可以在执行函数的时候把外部变量传进来,但是传进来之后就是本地的了
25、函数声明:函数体内部还可以声明函数,不过它们也都是本地的了
26、变量声明:这个优先级其实还是最低的,不过它们也都是最常用的
27、另外,还记得之前我们讨论过声明和定义的区别吧?当时我并没有说为什么要理解这个区别,不过现在是时候了,记住:Hosting只提升了命名,没有提升定义
28、Hosting只提升了命名,没有提升定义
29、这一点和我们接下来要讲到的东西息息相关,请看:
30、同学,在了解了Scoping&Hoisting之后,你知道怎么解释这一切了吧?
31、在第一个例子里,函数foo是一个声明,既然是声明就会被提升(我特意包裹了一个外层作用域,因为全局作用域需要你的想象,不是那么直观,但是道理是一样的),所以在执行foo()之前,作用域就知道函数foo的存在了。这叫做函数声明(FunctionDeclaration),函数声明会连通命名和函数体一起被提升至作用域顶部。
32、然而在第二个例子里,被提升的仅仅是变量名foo,至于它的定义依然停留在原处。因此在执行foo()之前,作用域只知道foo的命名,不知道它到底是什么,所以执行会报错(通常会是:undefinedisnotafunction)。这叫做函数表达式(FunctionExpression),函数表达式只有命名会被提升,定义的函数体则不会。
hoisting是什么意思,hoisting的意思翻译、用法、同义词、的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于JavaScript、hoisting是什么意思,hoisting的意思翻译、用法、同义词、的信息别忘了在本站进行查找哦。