

在JavaScript 中Hoisting 可以干嘛?
source link: https://www.fly63.com/article/detial/12643
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

什么是hoisting?
JavaScript中的hoisting(变量提升)是一种语言特性,它允许在代码执行之前声明变量和函数。在MDN 里面提到hoisting 并不是被定义的专有名词,而是用来理解JavaScript 在执行时如何运行的思路。
我们知道JavaScript 是单执行绪,也就是程式码是一行一行读取,但是用var宣告变数跟宣告函式会有被提早读取,被提升(Hoisting)的感觉。
来看看一些例子:
console.log(a);
//ReferenceError: a is not defined
console.log(a);
var a = 10;
// undefined
可以看到当使用var作宣告,提早读取时会回传undefined,你可以把他当作这样:
var a;
console.log(a); //undefined
a = 10;
也就是说var宣告会被提升,而赋值不会被提升。
再来看看function:
test(); //'hello world'
function test(){
console.log('hello world');
}
可以看到function被提早读取了,连函式内容都被提升了。
Hoisting 的顺序
知道了var、function有Hoisting 的效果,来看一下复杂的题目。
function test(a) {
console.log(a); // 印出 a
var a = 10; // var 宣告
function a(){
return 'hello world';
} // function 宣告
}
test(100);
这里面有总共有三个一样的名字,参数、function、var宣告,都是a,谁的优先权最大呢?
直接公布答案:
//output: [Function: a]
是不是有点出乎意料,答案是functiona 本身,所以说function的提升会优先于 var的宣告以及参数。
那我们继续比下去,把function拿掉:
function test(a) {
console.log(a); // 印出 a
var a = 10; // var 宣告
}
test(100);
这边就直接公布答案,答案就是100,所以总结来说,优先顺序是:function > parameter (参数) > var 宣告
那let 跟const 咧?
在ES6 新增了let跟const两个新的宣告变数方式,直接来看范例:
console.log(a);
let a = 10;
//ReferenceError: Cannot access 'a' before initialization
可以看到let跟const在宣告前读取会报错,那是不是代表他们没有hoisting?
那来看一个例子:
var a = 10; // var 宣告
function test() {
console.log(a); // 印出 a
let a = 100; // let 宣告
}
test(); //ReferenceError: Cannot access 'a' before initialization
如果let没有hoisting ,应该会印出外层宣告的 a = 10,但是!却跟上一个一样报错了。
所以由此可知,let跟const 也有hoisting 只是hoisting 后会报错,跟varhoisting 后会被初始化为undefined不同而已。
Temporal Dead Zone
而let跟const 会报错则有一个概念叫做TDZ(暂时性死区),也就是说在let跟 const被hoisting 之后到宣告之前,都是TDZ ,只要在TDZ 期间试着存取变数值,就会报错。
来看刚刚的例子:
var a = 10;
function test() {
// let 宣告 a 的 TDZ 開始
console.log(a); //試圖存取,報錯
let a = 100; // a 的 TDZ 結束
}
test();
为什么可以hoisting?
当了解了hoisting 之后,又跑出一个问题,JavaScript 不是单执行绪吗?为什么可以hoisting?
这其实跟JS 内部引擎有关系,这边就不细讲了,直接给结论:JS 内部引擎会在执行前编译程式码,也就是在这个阶段hoisting的。
所以hoisting 到底可以干嘛?
回到标题,hoisting 到底可以做什么,现在宣告变数也大多用let跟const,感觉没什么太大的用处。
其实在实作上明显的用处就是:
1. 函式被提升,可以不用管函式呼叫的先后顺序。
2. 函式之间可以互相呼叫,可以达成递回的效果。
总结以上,列出几个要点:
1.var跟function会有hoisting 的效果,var只会提升宣告,赋值不会。
2. 提升顺序:函式宣告> 函式参数> 变数宣告。
3.let跟const有hoisting 但在TDZ 间存取会报错。
链接: https://www.fly63.com/article/detial/12643
</div
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK