js 基礎(chǔ)(1) —— 提升

變量提升
提升:1. 變量提升 2. 函數(shù)提升

在解釋提升之前,有必要先了解一下作用域 和作用域鏈

注意:以下解釋非官方,個(gè)人理解

作用域:程序源代碼中定義這個(gè)變量的區(qū)域

作用域鏈:當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈來保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的變量和函數(shù)的有序訪問

eg:

var a=2;
console.log(a);
<!-- a在全局作用域中 輸出 2-->
function testa(){
  var a=3;
  console.log(a)
}
<!--a 既在全局作用域中又在局部作用域中,輸出 3-->
function testaa (){
  console.log(a);   
}
<!--a輸出 2-->

解釋:

a 在全局作用域中,在testa作用域中。

testa()執(zhí)行時(shí)瀏覽器會(huì)詢問引擎在哪里見過 a的聲明,引擎會(huì)優(yōu)先在當(dāng)前作用域?qū)ふ?,找到?既返回給客戶端,所以在testa()執(zhí)行時(shí),輸出的a=3;

testaa()執(zhí)行時(shí) 也是現(xiàn)在testaa的作用域中查找,發(fā)現(xiàn)并沒有a,然后會(huì)順著作用域鏈查找到全局作用域中的a,所以在testaa()中輸出的不是 undefined 也不是RefrenceError 而是 2

  1. 變量提升
console.log(a)
var a = 2;
<!--輸出 undefined-->

為什么不是RefrenceError?

由于js是編譯語言,在引擎進(jìn)程編譯的過程中會(huì)先進(jìn)行變量的聲明,然后才會(huì)進(jìn)行賦值操作,所以上述代碼實(shí)際的執(zhí)行過程是這樣的:

var a ;
console.log(a);
a =2 ;

由于變量存在提升現(xiàn)象,會(huì)出現(xiàn)很多問題,其中就包括閉包(這里只簡(jiǎn)要介紹,詳見js基礎(chǔ)(2)):

var a=[];
for(var i =0;i<3;i++){
    a[i]=function(){
        return i;
    }
}
console.log(a[0]()); // 3 
console.log(a[1]()); // 3 
console.log(a[2]()); // 3

為什么會(huì)全是3 呢

因?yàn)樵趫?zhí)行a[0]()時(shí),在該函數(shù)的作用域中沒有i的定義,所以回去找全局作用域中的i的值 此時(shí)在全局作用域中i 的值為3,所以所有的函數(shù)執(zhí)行之后都是 3;

解決方式:

var a=[];
for(var i =0;i<3;i++){
    a[i]=function(i){
        return function(){return i}
    }(i)
}
console.log(a[0]()); // 0
console.log(a[1]()); // 1
console.log(a[2]()); // 2

相當(dāng)于在a[i]這個(gè)函數(shù)的作用域中聲明了一個(gè)i變量 并且賦予了不同的值,所以會(huì)輸出 0 1 2

ES6 中針對(duì)變量的提升給出了一種解決方案,新增了兩種變量類型 const 和let,用這兩種類型聲明的變量存在暫時(shí)性死區(qū),并且在編譯階段 由const和let聲明的變量是未定義狀態(tài),所以就避免了變量提升。

console.log(a) ; //RefrenceError 未定義
let a =3;
var a=[];
for(let i =0;i<3;i++){
    a[i]=function(){
        return i;
    }
}
console.log(a[0]()); // 0 
console.log(a[1]()); // 1 
console.log(a[2]()); // 2  解決閉包問題
  1. 函數(shù)提升
test(); //輸出test 
function test(){
    console.log('test');
}

test()執(zhí)行時(shí) 并沒有報(bào)錯(cuò),這就由于函數(shù)提升

由變量定義的函數(shù) 不提升,但是也存在變量聲明的提升

console.log(test());
var test =function (){
    console.log('test');
}

輸出 TypeError test不是一個(gè)函數(shù) ,console.log(test);輸出 test為undefined,還是會(huì)存在變量提升的現(xiàn)象

console.log(test());
const test =function (){
    console.log('test');
}

輸出 RefrenceError test 未定義 ,同樣說明由const let定義的在預(yù)編譯階段都認(rèn)為沒有定義過,只有賦值完成之后才能引用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,578評(píng)論 19 139
  • 繼承 一、混入式繼承 二、原型繼承 利用原型中的成員可以被和其相關(guān)的對(duì)象共享這一特性,可以實(shí)現(xiàn)繼承,這種實(shí)現(xiàn)繼承的...
    magic_pill閱讀 1,128評(píng)論 0 3
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,624評(píng)論 30 472
  • 一提到創(chuàng)新,你的腦海中浮現(xiàn)什么?想必是有智慧的人,思想超前,能力超群,如喬布斯,如馬斯克;有創(chuàng)意的團(tuán)體及公司,如G...
    心蓮Kallen閱讀 1,345評(píng)論 4 8
  • 那日,那月,那季,那年,我攀過懸崖峭壁,走過泥濘不堪的小路,走過蜿蜒曲折的山間小路,走過寬闊的大道,轉(zhuǎn)過雪域高原的...
    盧屹閱讀 186評(píng)論 3 4

友情鏈接更多精彩內(nèi)容