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