摘要:換句話說,在代碼執(zhí)行之前,會對作用域鏈中所有變量和函數(shù)聲明先處理完先。總結(jié)一句話就是只有聲明被提升,而賦值或其他運算會留在原地。為其聲明變量隱性劫持到所在區(qū)域中。
之前一直覺會認為javascript代碼執(zhí)行是由上到下一行行執(zhí)行的。自從看了《你不知道的JS》后發(fā)現(xiàn)這個觀點并不完全正確。先來給大家舉一個書本上的的例子:
var a="hello world"; var a; console.log(a);
一開始我覺得輸出的是undefined。但是真正的結(jié)果是hello world。帶著疑問再看另外一段代碼:
console.log(a); var a="hello world";
借鑒與上面的例子會認為會輸出一個hello world,或者是拋出一個沒有聲明的異常錯誤,然而發(fā)現(xiàn)這兩種想法也是錯誤。輸出的結(jié)果是‘undefined’。這書非常人性化的總結(jié)出了結(jié)論是:
引擎解釋javascript代碼的之前會對其進行編譯。在編譯過程中會查找所有聲明,并用合適作用域?qū)⑺麄冴P(guān)聯(lián)起來。換句話說,在代碼執(zhí)行之前,會對作用域鏈中所有變量和函數(shù)聲明先處理完先。所以,當(dāng)遇到var a="hello world"中是 var a是先在編譯階段執(zhí)行,然后在執(zhí)行a="hello world"。所以,第一段代碼實質(zhì)上是:
var a; a="hello world"; console.log(a);
所以輸出的就就是helloworld。總結(jié)一句話就是:只有聲明被提升,而賦值或其他運算會留在原地。所以第二段代碼實際上就是:
var a; console.log(a); a="hello world";
介紹完這兩個經(jīng)典例子是時候來看看一下這個例子了:
var name = "world"; (function () { if (typeof name == "undefined") { var name = "yang"; console.log("Hello " + name) } else { console.log("Hello " + name) } })()
根據(jù)javascript的運行機制和javascript沒有塊作用域這個特點,可以得出,變量name會聲明提升移至作用域 scope (全局域或者當(dāng)前函數(shù)作用域) 頂部的。所以上述代碼就相當(dāng)于:
var name = "world"; (function () { var name; if (typeof name == "undefined") { var name = "yang"; console.log("Hello " + name) } else { console.log("Hello " + name) } })()
因此,if判斷的時候typeof name == "undefined"是true。所以會執(zhí)行條件為true里面的代碼。輸出就是Hello yang。
那么如果想實現(xiàn)上面的函數(shù),我們該如何實現(xiàn)?答案非常簡單那就創(chuàng)建塊作用域了。如何最簡單的創(chuàng)建塊作用域呢?那當(dāng)然是采用es6的新特性let關(guān)鍵字。let關(guān)鍵字可以將變量綁定到所在的任意區(qū)域中通常在{...}中。換句話說。let為其聲明變量隱性劫持到所在區(qū)域中。下列例子中:let就綁定到if (typeof name == "undefined") {...}中。所以name不會被提升,所以判斷就為假,于是就可以輸出我們期待已久的‘helloworld’。
var name = "world"; (function () { if (typeof name == "undefined") { let name = "yang"; console.log("Hello " + name) } else { console.log("Hello " + name) } })()
注意點:let所在的塊級作用域,在聲明代碼被運行前,是不會像var那樣會被查找到,提前聲明,而是運行到了該代碼才會被聲明執(zhí)行。下面例子很好說明這個問題:
(function (){ console.log(b); let b=2; })()
謝謝大家觀看,大家有什么好看法可以提出來討論討論。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87981.html
摘要:不同的是函數(shù)體并不會再被提升至函數(shù)作用域頭部,而僅會被提升到塊級作用域頭部避免全局變量在計算機編程中,全局變量指的是在所有作用域中都能訪問的變量。 ES6 變量作用域與提升:變量的生命周期詳解從屬于筆者的現(xiàn)代 JavaScript 開發(fā):語法基礎(chǔ)與實踐技巧系列文章。本文詳細討論了 JavaScript 中作用域、執(zhí)行上下文、不同作用域下變量提升與函數(shù)提升的表現(xiàn)、頂層對象以及如何避免創(chuàng)建...
摘要:注意是前面,而不是最前面,因為變量聲明提升的優(yōu)先級別要低于函數(shù)聲明提升。分解后是這樣從以下代碼可以看出這也印證了變量聲明提升與變量定義分兩步走的結(jié)論。 函數(shù)聲明 定義函數(shù)有兩種方式: 一種是函數(shù)聲明,另一種是函數(shù)表達式。函數(shù)聲明語法如下: function functionName(arg0, arg1, arg2) { // 函數(shù)體 } 函數(shù)聲明提升 所謂的函數(shù)聲明提升,是指...
摘要:要理解函數(shù)的提升行為,讓我們先解析什么是的提升。也就是說聲明提升了,賦值還留著原地,等待執(zhí)行。聲明被提升,而包括函數(shù)表達式的賦值在內(nèi)的賦值操作并不會提升,而是留在原地等待執(zhí)行。 javaScript自上而下執(zhí)行的順序受到很多新手和部分老手的共識,但是這其實并不完全正確,這涉及到j(luò)s的編譯過程,這方面我們稍后會聊到,先考慮下面代碼: window.onload = function(){...
摘要:函數(shù)表達式又名匿名函數(shù)為變量賦的值是函數(shù)定義本身。在語言里任何匿名函數(shù)都是屬于對象。這種情況下,就叫做回調(diào)函數(shù)。如上面代碼示例展示了文檔單擊事件時以冒泡模式傳遞給回調(diào)函數(shù)的特別適用于事件驅(qū)動編程,因為回調(diào)模式支持程序以異步方式運行。 JavaScript設(shè)計模式的作用是提高代碼的重用性,可讀性,使代碼更容易的維護和擴展 在javascript中,函數(shù)是一類對象,這表示他可以作為參數(shù)傳遞...
摘要:命令用于規(guī)定模塊的對外接口,命令用于輸入其他模塊提供的功能所以在一定程度上來說,也具有聲明變量的功能。當(dāng)沒有聲明,直接給變量賦值時,會隱式地給變量聲明,此時這個變量作為全局變量存在。 前言 如果文章中有出現(xiàn)紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過 在ES5階段,JavaScript 使用 var 和 function 來聲明變量, ES6 中又添加了let、const、imp...
閱讀 1056·2021-11-25 09:43
閱讀 1426·2021-11-18 10:02
閱讀 1869·2021-11-02 14:41
閱讀 2381·2019-08-30 15:55
閱讀 1080·2019-08-29 16:18
閱讀 2564·2019-08-29 14:15
閱讀 1400·2019-08-26 18:13
閱讀 746·2019-08-26 10:27