摘要:注意是前面,而不是最前面,因為變量聲明提升的優(yōu)先級別要低于函數(shù)聲明提升。分解后是這樣從以下代碼可以看出這也印證了變量聲明提升與變量定義分兩步走的結論。
函數(shù)聲明
定義函數(shù)有兩種方式: 一種是函數(shù)聲明,另一種是函數(shù)表達式。
函數(shù)聲明語法如下:
function functionName(arg0, arg1, arg2) { // 函數(shù)體 }函數(shù)聲明提升
所謂的函數(shù)聲明提升,是指在一個作用域中,如果聲明了一個函數(shù),那么在代碼執(zhí)行的時候,會將這個聲明提升到整個作用域的最前面來執(zhí)行??聪旅娴睦?。
printString("hello world") function printString(string) { console.log(string) }
將代碼整體復制到控制臺,會打印出hello world。
再看函數(shù)內(nèi)部作用域:
function outer() { inner("hello world") function inner(string) { console.log(string) } } outer() // hello world
這樣也得到了正確的輸出。
為什么在函數(shù)聲明之前就可以調(diào)用呢?就是因為函數(shù)聲明提升。
所以,無論函數(shù)聲明被寫在所處作用域的哪里,都會被提升到這段代碼的最前面。
如果在已經(jīng)聲明了一個函數(shù)的情況下,聲明另一個同名函數(shù),將會覆蓋前面一個。
function b() {console.log(1)} function b() {console.log(2)} b() // 2
上述代碼中,真正執(zhí)行的是后面聲明的函數(shù)。
函數(shù)聲明的實質函數(shù)聲明實質上是定義了一個變量,該變量是Function的實例, 它指向了一個函數(shù)。
function newF() { console.log("hello") } console.log(typeof newF) // "function" console.log(newF instanceof Function) // true
這樣的話,就不難理解為什么聲明重名函數(shù),會覆蓋前面一個了,這相當于重新給這個變量賦了一個值。
變量定義定義一個變量的語法如下:
var a var b
實際上是用var聲明了一個新的變量,變量被聲明時默認值為undefined。
變量聲明并初始化的實質這里說的變量聲明并初始化是指下面這種方式:
var a = 1;
實際上這行代碼是分兩步執(zhí)行的:
先聲明變量
var a = undefined;
給變量賦值
a = 1;
這也是為什么可以用一個變量給另一個變量做初始化的原因。看下面的代碼:
var b = 3; var a = b console.log(a) // 3
實際上分了四步:
聲明b: var b = undefined;
生命a: var a = undefined;
給b賦值: b = 3;
給a賦值: a = b;
變量聲明提升變量的聲明也可以提升,也就是說JS在執(zhí)行時,會把變量聲明的代碼提升到這個作用域代碼段的前面。注意:是前面,而不是最前面,因為變量聲明提升的優(yōu)先級別要低于函數(shù)聲明提升。
看下面代碼:
console.log(foo) var foo = 3
執(zhí)行結果是undefined。實際執(zhí)行順序為:
var foo = undefined console.log(foo) foo = 3重復聲明變量
如果聲明一個已經(jīng)聲明過的變量,JS會忽略第二次聲明。但是如果在聲明時給變量賦值,那么會覆蓋之前的值。
var foo1 = 3; var foo1 console.log(foo1) // 3
拆開來看,是如下代碼:
var foo1 = undefined; foo1 = 3; var foo1 = undefined; // 這行代碼被忽略。不會執(zhí)行 console.log(foo1) // 3聲明一個與函數(shù)聲明的名字相同的變量
如果聲明了一個變量,這個變量和某個函數(shù)聲明具有同樣的名字,那么也會忽略這個變量聲明。
function foo3() {} var foo3 console.log(foo3) // function foo3() {}
但是如果聲明變量時進行了初始化就不一樣了,相當于給變量重新賦值:
function foo3() {} var foo3 = 3 console.log(foo3) // 3函數(shù)表達式
另一種定義函數(shù)的方式是函數(shù)表達式,語法如下:
var func = function(){ console.log("hello") }
實際上,這就是一個變量聲明并初始化的代碼。分解后是這樣:
var func = undefined; func = function(){ console.log("hello") }
從以下代碼可以看出:
console.log(func) // undefined var func = function(){} console.log(func) // function (){}
這也印證了變量聲明提升與變量定義分兩步走的結論。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/84045.html
摘要:不同的是函數(shù)體并不會再被提升至函數(shù)作用域頭部,而僅會被提升到塊級作用域頭部避免全局變量在計算機編程中,全局變量指的是在所有作用域中都能訪問的變量。 ES6 變量作用域與提升:變量的生命周期詳解從屬于筆者的現(xiàn)代 JavaScript 開發(fā):語法基礎與實踐技巧系列文章。本文詳細討論了 JavaScript 中作用域、執(zhí)行上下文、不同作用域下變量提升與函數(shù)提升的表現(xiàn)、頂層對象以及如何避免創(chuàng)建...
摘要:命令用于規(guī)定模塊的對外接口,命令用于輸入其他模塊提供的功能所以在一定程度上來說,也具有聲明變量的功能。當沒有聲明,直接給變量賦值時,會隱式地給變量聲明,此時這個變量作為全局變量存在。 前言 如果文章中有出現(xiàn)紕漏、錯誤之處,還請看到的小伙伴多多指教,先行謝過 在ES5階段,JavaScript 使用 var 和 function 來聲明變量, ES6 中又添加了let、const、imp...
摘要:函數(shù)表達式又名匿名函數(shù)為變量賦的值是函數(shù)定義本身。在語言里任何匿名函數(shù)都是屬于對象。這種情況下,就叫做回調(diào)函數(shù)。如上面代碼示例展示了文檔單擊事件時以冒泡模式傳遞給回調(diào)函數(shù)的特別適用于事件驅動編程,因為回調(diào)模式支持程序以異步方式運行。 JavaScript設計模式的作用是提高代碼的重用性,可讀性,使代碼更容易的維護和擴展 在javascript中,函數(shù)是一類對象,這表示他可以作為參數(shù)傳遞...
摘要:換句話說,在代碼執(zhí)行之前,會對作用域鏈中所有變量和函數(shù)聲明先處理完先。總結一句話就是只有聲明被提升,而賦值或其他運算會留在原地。為其聲明變量隱性劫持到所在區(qū)域中。 之前一直覺會認為javascript代碼執(zhí)行是由上到下一行行執(zhí)行的。自從看了《你不知道的JS》后發(fā)現(xiàn)這個觀點并不完全正確。先來給大家舉一個書本上的的例子: var a=hello world; var a; co...
摘要:凍結對象可以使用方法。對象的解構賦值必須要屬性名相同,順序毫無影響。數(shù)組解構賦值默認值,當?shù)忍栍疫叺闹禃r,默認值生效。 let變量 let聲明的變量在let命令所在的代碼塊中有效。不存在變量提升,只能先聲明后使用。 暫存死區(qū) 如果區(qū)塊中存在let和const命令,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量。 var a = 1; { ...
閱讀 2779·2021-11-19 09:40
閱讀 5468·2021-09-27 14:10
閱讀 2129·2021-09-04 16:45
閱讀 1524·2021-07-25 21:37
閱讀 3025·2019-08-30 10:57
閱讀 3007·2019-08-28 17:59
閱讀 1077·2019-08-26 13:46
閱讀 1437·2019-08-26 13:27