今早做了一道牛客網上的題目(下圖),做的時候就很不確定,做完看到下面的評論就懵了,不知道變量提升和函數提升之間的優先級到底是怎么樣的。
查了一下,自己寫了幾個例子之后就比較明朗了。我的參考鏈接是這個:JS中變量提升與函數提升及其優先級
首先是對於提升的原因:JS引擎讀取代碼時,分為兩步,第一步是對整個JS代碼的解析讀取,第二步是代碼的執行。提升發生在第一步,所以在代碼執行之前,瀏覽器的解析器遇到變量名(注意:只能是用var聲明的變量,用let或者const聲明的變量都不存在提升的問題)和函數聲明(注意:JS引擎嚴格規定句首用 function 的才能算作函數聲明,其余的雜牌聲明只能算作函數表達式)提升至當前作用域的最前面。
變量提升(只針對var)的例子:
console.log(a);//undefined var a = 'hi'; console.log(a);//'hi'
上述代碼在解析后相當於如下:
var a;//只定義不聲明就默認是undefined console.log(a);//undefined a='hi'; console.log(a);//hi
函數提升(只針對函數聲明)的例子:
console.log(a); //f a(){console.log('hi');} console.log(b); //undefined function a() { console.log('hi'); } var b = function() { console.log('ok'); }
上述代碼在變量提升和函數提升之后變成如下:
function a() { console.log('hi'); } var b;//undefined; console.log(a); //f a(){console.log('hi');} console.log(b); //undefined b = function() { console.log('ok'); }
二者優先級:函數提升會優先於變量提升,而且不會被同名的變量覆蓋,但是,如果這個同名變量已經賦值了,那函數變量就會被覆蓋。當二者同時存在時,會先指向函數聲明。
console.log(a); //f a() {...} console.log(a()); //2 var a = 1; function a() { console.log(2); } console.log(a); //1 a = 3; console.log(a()); //報錯,現在的函數a已經被賦值過后的變量a給覆蓋了,無法再調用a()
上述代碼相當於如下:
function a() { console.log(2); } var a; console.log(a); //f a() {...} console.log(a()); //2 a = 1; console.log(a); //1 a = 3; console.log(a()); //報錯,現在的函數a已經被賦值過后的變量a給覆蓋了,無法再調用a()