国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS學(xué)習(xí)系列 04 - 提升

liuyix / 1390人閱讀

摘要:第二個(gè)賦值聲明會(huì)被留在原地等待執(zhí)行階段。這個(gè)過(guò)程就叫作提升。還有一點(diǎn),函數(shù)聲明會(huì)被提升,但是函數(shù)表達(dá)式不會(huì)被提升。

到目前為止,大家應(yīng)該很熟悉作用域的概念了,以及根據(jù)聲明的位置和方式將變量分配給作用域的相關(guān)原理了。函數(shù)作用域和塊作用域的行為是一樣的,可以總結(jié)為:任何聲明在某個(gè)作用域內(nèi)的變量,都將屬于這個(gè)作用域。

但是作用域同其中的變量聲明出現(xiàn)的位置有某種微妙的關(guān)系,而這個(gè)細(xì)節(jié)就是我們這節(jié)要探討的內(nèi)容。

1. 聲明提升

先看代碼:

a = 2;

var a;

console.log(a);

大家認(rèn)為這里會(huì)輸出什么?

有一些人認(rèn)為是 undefined ,因?yàn)?var a; 是在 a = 2; 之后,所以會(huì)覺(jué)得 undefined 覆蓋了 a 的值。但是,真正的結(jié)果是 2 。

再看一段代碼:

console.log(a);

var a = 2;

鑒于上一個(gè)例子,有些人會(huì)認(rèn)為這里會(huì)輸出 2 ,也有人認(rèn)為由于 a 在使用前并沒(méi)有聲明,所以這里會(huì)報(bào)錯(cuò)。但是,這里的結(jié)果是 undefined 。

之前討論編譯器的時(shí)候,我們知道 JS 引擎會(huì)在解釋代碼之前首先對(duì)其進(jìn)行編譯。編譯階段的第一部分工作就是找到所有的聲明,并用合適的作用域?qū)⑺鼈冴P(guān)聯(lián)起來(lái)。

因此,正確的思路是,包括變量和函數(shù)在內(nèi)的所有聲明都會(huì)在任何代碼執(zhí)行前首先被處理。

當(dāng)你看到 var a = 2; 時(shí),JavaScript 實(shí)際上會(huì)將其看成兩個(gè)聲明:var a;a = 2; 。第一個(gè)定義聲明是在編譯階段進(jìn)行的。第二個(gè)賦值聲明會(huì)被留在原地等待執(zhí)行階段。

所以,在第一個(gè)例子中,代碼的等價(jià)形式是這樣的:

var a;

a = 2;

console.log(a);

第二個(gè)例子中,代碼的等價(jià)形式是這樣的:

var a;

console.log(a);

a = 2;

這個(gè)過(guò)程就好像是變量和函數(shù)聲明從它們的代碼中出現(xiàn)的位置被“移動(dòng)”到了最上面。這個(gè)過(guò)程就叫作“提升”。

注意,只有聲明本身會(huì)被提升,而賦值操作和其他運(yùn)行邏輯都會(huì)停留在原地,想象一下,如果提升會(huì)改變代碼的執(zhí)行順序,那么會(huì)造成非常嚴(yán)重的破壞。

還有一點(diǎn),函數(shù)聲明會(huì)被提升,但是函數(shù)表達(dá)式不會(huì)被提升。

foo();      // 報(bào)錯(cuò),TypeError: foo is not a function,因?yàn)檫@里 foo 是 undefined,并不是一個(gè)函數(shù)

var foo = function foo() {
    // something else
}

這段程序中的變量標(biāo)識(shí)符 foo 被提升并分配給所在的作用域(在這里是全局作用域),因此 foo() 不會(huì)導(dǎo)致 ReferenceError 。但是,foo 此時(shí)并沒(méi)有賦值(如果它是一個(gè)函數(shù)聲明而不是函數(shù)表達(dá)式,那么就會(huì)被賦值)。foo() 由于對(duì) undefined 值進(jìn)行函數(shù)調(diào)用而導(dǎo)致非法操作,所以會(huì)拋出 TypeError 異常。

同時(shí),即使是具名函數(shù)表達(dá)式,名稱標(biāo)識(shí)符在賦值之前也無(wú)法在所在作用域中使用:

foo();
bar();

var foo = function bar () {
    // something else
};

這段代碼經(jīng)過(guò)提升后,實(shí)際上等價(jià)于:

var foo;

foo();
bar();

foo = function () {
    var bar = ...self...
    // something else
};
2. 函數(shù)優(yōu)先

函數(shù)聲明和變量聲明都會(huì)被提升。但是一個(gè)值得注意的細(xì)節(jié)是,函數(shù)聲明會(huì)首先被提升,然后才是變量。

考慮如下代碼:

foo();      // 1

var foo;

function foo () {
   console.log(1);
}

foo = function () {
   console.log(2);
};

這里會(huì)輸出 1 而不是 2 。這段代碼其實(shí)等價(jià)于:

function foo () {
   console.log(1);
}

foo();      // 1

foo = function () {
   console.log(2);
};

var foo; 盡管出現(xiàn)在 function foo() {...} 聲明之前,但是它是重復(fù)聲明,所以會(huì)被編譯器忽略,因?yàn)楹瘮?shù)聲明會(huì)被提升到變量聲明之前。

注意,盡管重復(fù)的 var 聲明會(huì)被忽略,但重復(fù)的函數(shù)聲明卻會(huì)覆蓋前一個(gè)同名函數(shù)。

foo();      // 3

function foo () {
   console.log(1);
}

var foo = function () {
   console.log(2);
};      

foo();        // 2

function foo () {
   cosole.log(3);
}

這個(gè)例子充分說(shuō)明了在同一個(gè)作用域中進(jìn)行重復(fù)定義是非常糟糕的,而且經(jīng)常會(huì)導(dǎo)致各種奇怪的問(wèn)題。上面那個(gè)例子,等價(jià)于:

function foo () {
   cosole.log(3);
}

foo();      // 3

foo = function () {
   console.log(2);
};      

foo();        // 2

還有一些人會(huì)犯如下錯(cuò)誤:

foo();      // 2

var a = true;

if (a) {
   function foo () {
      console.log(1);
   }
} else {
   function foo () {
      console.log(2);
   }
}

因?yàn)?if 并沒(méi)有塊作用域,所以這里的函數(shù)聲明會(huì)提升到其作用域最前邊,而后一個(gè) function 聲明會(huì)覆蓋前一個(gè),所以這里結(jié)果是 2 。這里代碼等價(jià)如下:

function foo () {
   console.log(2);
}

var a;

foo();      // 2

a = true;

if (a) {

} else {

}
3. 總結(jié)

我們習(xí)慣將 var a = 2; 看作一個(gè)聲明,而實(shí)際上 JavaScript 引擎并不這么認(rèn)為。它將 var a;a = 2; 當(dāng)作兩個(gè)多帶帶的聲明,第一個(gè)是編譯階段的任務(wù),而第二個(gè)則是執(zhí)行階段的任務(wù)。

這意味著無(wú)論作用域中的聲明出現(xiàn)在什么地方,都將在代碼本身被執(zhí)行前首先被處理(預(yù)編譯)。可以將這個(gè)過(guò)程想象成所有的聲明(變量和函數(shù))都會(huì)被“移動(dòng)”到各自的作用域的最頂端,這個(gè)過(guò)程叫作提升

歡迎關(guān)注我的公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/81659.html

相關(guān)文章

  • ES2015入門系列10-類 classes

    摘要:我們繼續(xù),這次來(lái)聊聊類。,編寫代碼角色基類判斷角色是否死亡升級(jí)受到傷害攻擊普通攻擊攻擊了造成了點(diǎn)傷害攻擊,有概率是用必殺攻擊必殺攻擊使用必殺攻擊了造成了點(diǎn)傷害游戲世界權(quán)利的游戲初始化英雄怪物集合,模擬簡(jiǎn)單的游戲關(guān)卡。 OK, 我們繼續(xù),這次來(lái)聊聊類。 內(nèi)有 Jon Snow大戰(zhàn)異鬼, ? 熟悉后端的朋友們對(duì)類肯定都不陌生,如下面一段PHP的代碼: class Human { pr...

    Wuv1Up 評(píng)論0 收藏0
  • 前端每周清單半年盤點(diǎn)之 Angular 篇

    摘要:延伸閱讀學(xué)習(xí)與實(shí)踐資料索引與前端工程化實(shí)踐前端每周清單半年盤點(diǎn)之篇前端每周清單半年盤點(diǎn)之與篇前端每周清單半年盤點(diǎn)之篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開發(fā)教程、工程實(shí)踐、深度閱讀、開源項(xiàng)目、巔峰人生等欄目。歡迎關(guān)注【前端之巔】微信公眾號(hào)(ID:frontshow),及時(shí)獲取前端每周清單;本文則是對(duì)于半年來(lái)發(fā)布的前端每周清單...

    LeviDing 評(píng)論0 收藏0
  • 我的阿里之路+Java面經(jīng)考點(diǎn)

    摘要:我的是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)。因?yàn)槲倚睦砗芮宄业哪繕?biāo)是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來(lái)的學(xué)習(xí)計(jì)劃,將我的短期目標(biāo)更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)offer。然后五月懷著忐忑的心情開始了螞蟻金...

    姘擱『 評(píng)論0 收藏0
  • 前端每周清單第 11 期:Angular 4.1支持TypeScript 2.3,Vue 2.3優(yōu)化

    摘要:斯坦福宣布使用作為計(jì)算機(jī)課程的首選語(yǔ)言近日,某位有年教學(xué)經(jīng)驗(yàn)的斯坦福教授決定放棄,而使用作為計(jì)算機(jī)入門課程的教學(xué)語(yǔ)言。斯坦福官方站點(diǎn)將它們新的課程描述為是最流行的構(gòu)建交互式的開發(fā)語(yǔ)言,本課程會(huì)用講解中的實(shí)例。 前端每周清單第 11 期:Angular 4.1支持TypeScript 2.3,Vue 2.3優(yōu)化服務(wù)端渲染,優(yōu)秀React界面框架合集 為InfoQ中文站特供稿件,首發(fā)地址為...

    warkiz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

liuyix

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<