在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問(wèn)答/HTML/ js中為什么要進(jìn)行變量提升?

js中為什么要進(jìn)行變量提升?

昨天碰到一不好“對(duì)付”人,問(wèn)了我這個(gè)問(wèn)題~~
我查了,大家都是討論什么是變量提升和函數(shù)提升。。。
于是,我仔細(xì)想了一下,有什么好問(wèn)的呢,能告訴自己的解釋就是:為了體現(xiàn)它的作用域?使其在作用域內(nèi)有效....

請(qǐng)問(wèn)哪位有沒(méi)有更好、更深、更全面的解釋~~比如涉及到j(luò)s底層存儲(chǔ)之類(lèi)

回答
編輯回答
陌離殤

我覺(jué)得你想問(wèn)的應(yīng)該是JS為什么要進(jìn)行變量提升,而不是按照順序解析和綁定變量這么一個(gè)問(wèn)題吧?

好,下面就談?wù)勎覍?duì)這個(gè)問(wèn)題的看法。

首先,我們都知道,JS拿到一段代碼或一個(gè)函數(shù)的時(shí)候,會(huì)有兩步主要操作,即解析與執(zhí)行。

在解析階段,JS會(huì)檢查語(yǔ)法,并對(duì)函數(shù)進(jìn)行預(yù)編譯。

所以當(dāng)函數(shù)的代碼有語(yǔ)法錯(cuò)誤的時(shí)候,在函數(shù)執(zhí)行前就會(huì)報(bào)錯(cuò)(SyntaxError)。

接下來(lái)是執(zhí)行階段,這個(gè)階段沒(méi)什么好講的,就是逐條解釋每條語(yǔ)句并執(zhí)行。

弄明白JS函數(shù)的兩個(gè)階段之后,下面我們就來(lái)談?wù)劼暶魈嵘膯?wèn)題。聲明提升就是函數(shù)中任何位置所聲明的變量或函數(shù),都會(huì)自動(dòng)“提”到函數(shù)的最前面,就好像它們是在函數(shù)的開(kāi)頭聲明的一樣。

為什么要提升變量和函數(shù)的聲明?表面上看,是因?yàn)樽饔糜?。確實(shí),在ES6之前,JS并沒(méi)有塊級(jí)作用域,所有變量要么具有全局作用域,要么具有函數(shù)級(jí)作用域。

但是進(jìn)一步思考就會(huì)發(fā)現(xiàn),這只是聲明提升的結(jié)果,而不能成為必須要這么做的理由。后來(lái)加入的let變量就是一個(gè)例子。

那么究竟為什么要進(jìn)行聲明提升呢?其實(shí)我認(rèn)為主要原因有兩點(diǎn):

  • 聲明提升可以提高性能

前面說(shuō)過(guò),JS會(huì)在函數(shù)執(zhí)行前對(duì)其進(jìn)行語(yǔ)法檢查和預(yù)編譯,并且這一操作只會(huì)進(jìn)行一次。之所以要這么做,一個(gè)目的在于提高性能。因?yàn)槿绻麤](méi)有這一步,那么每次執(zhí)行函數(shù)前都必須重新解析一遍該函數(shù),而這是沒(méi)有必要的,因?yàn)楹瘮?shù)的代碼并不會(huì)改變,解析一遍就夠了。

另外,解析的過(guò)程中,還會(huì)為函數(shù)生成預(yù)編譯代碼。在預(yù)編譯時(shí),會(huì)統(tǒng)計(jì)該函數(shù)聲明了哪些變量、創(chuàng)建了哪些函數(shù)(注:這里就是聲明提升),并對(duì)函數(shù)的代碼進(jìn)行壓縮,去除注釋、不必要的空白等。這樣做的好處是每次執(zhí)行函數(shù)時(shí)都可以直接為該函數(shù)分配??臻g(不需要再解析一遍去獲取函數(shù)中聲明了哪些變量,注:這也是聲明提升的好處),并且代碼執(zhí)行更快(因?yàn)閴嚎s而變短了)。兩個(gè)好處都會(huì)提高執(zhí)行函數(shù)的性能。

  • 容錯(cuò)性更好

我們知道,JS是一種腳本語(yǔ)言,在發(fā)布之后很長(zhǎng)時(shí)間內(nèi)都沒(méi)有為程序員提供編譯器、調(diào)試器、語(yǔ)法檢查器等工具。在很長(zhǎng)一段時(shí)間內(nèi)其地位始終是Web頁(yè)面的附屬品,僅僅用來(lái)給頁(yè)面添加一些非必要的動(dòng)態(tài)效果,并且其開(kāi)發(fā)和部署也具有很強(qiáng)的隨意性,未經(jīng)過(guò)調(diào)試和測(cè)試的代碼比比皆是。直到后來(lái)Ajax的出現(xiàn),這一情況才逐步改變。

在這種情況下,提高JS的容錯(cuò)就是很有好處的了。而聲明提升可以在一定程度上提高JS的容錯(cuò)性??聪旅娴睦樱?/p>

function foo() {
    console.log(a);
    var a;
}

如果沒(méi)有聲明提升,這段代碼就是錯(cuò)的,但有了聲明提升,這段代碼便可以正常運(yùn)行。

但是你可能會(huì)說(shuō),正常代碼不應(yīng)該這么寫(xiě),就像其他語(yǔ)言,變量肯定要先聲明再使用啊,因此這一點(diǎn)只要稍加注意就能避免,不是嗎?

確實(shí)如此,但稍加注意也要投入注意力不是?尤其是在修改別人的代碼的時(shí)候,這種在聲明前就使用的情況就更容易發(fā)生了。

如果上面的例子無(wú)法說(shuō)服你,下面再看一個(gè)更有代表性的例子:

function foo() {
    if (...) {
        var a;
    }
    console.log(a);
}

這種情況更常見(jiàn)了,在寫(xiě)if語(yǔ)句的時(shí)候,我發(fā)現(xiàn)我需要一個(gè)變量a,于是順手寫(xiě)了var a = ...;,但是到后面我又發(fā)現(xiàn)這個(gè)變量在if語(yǔ)句外面也會(huì)用到,于是我忘記了回頭去把a(bǔ)的聲明提到if外面。當(dāng)if的條件不滿(mǎn)足的時(shí)候,里面的代碼根本不會(huì)執(zhí)行,如果沒(méi)有聲明提升,那么這時(shí)候a將不會(huì)存在。

而要在代碼層面完全避免這種情況顯然需要投入更多的注意力才行了。當(dāng)然,你可能會(huì)說(shuō),這個(gè)好像不是聲明提升,變量a本來(lái)就是在使用前定義的啊。

這么說(shuō)沒(méi)有錯(cuò),但是你不能不承認(rèn)JS的變量沒(méi)有塊作用域這一事實(shí)與聲明提升有很大關(guān)系。比如,如果把var a換成let a

總結(jié):

  1. 解析和預(yù)編譯過(guò)程中的聲明提升可以提高性能,讓函數(shù)可以在執(zhí)行時(shí)預(yù)先為變量分配??臻g
  2. 聲明提升還可以提高JS代碼的容錯(cuò)性,使一些不規(guī)范的代碼也可以正常執(zhí)行
2018年4月16日 12:09
編輯回答
莓森
2017年9月19日 08:38
編輯回答
挽歌
var a =2;

拆分成

var a;  //編譯階段,找到所有的聲明,并用合適的作用域?qū)⑺麄冴P(guān)聯(lián)起來(lái)
a=2;    //賦值階段,編譯階段以后執(zhí)行
2018年3月15日 13:30