[英]JavaScript variable hoisting example
我有一個關於 JavaScript 中變量提升的問題。
考慮以下示例:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
我實際上很困惑為什么typeof myName
作為string返回。
根據我的理解,該示例將按以下方式處理;
function myName ()
)將被提升到頂部,然后var myName = "Richard"
這一行(因為函數聲明優先於變量聲明)。 但是,由於已經存在名為“myName”的屬性,因此該語句將被忽略。 因此typeof myName
應該作為函數(而不是字符串)返回。
我的理解哪里不對?
JavaScript 有一個動態類型系統,即變量的類型可以隨時間改變。 基本上,您編寫的內容是正確的:首先,函數聲明會運行(在加載文件時),但隨后存儲在變量myName
的函數被字符串覆蓋。
唯一被忽略的是對var
的調用,因為變量實際上已經聲明了。
但是重新定義一個變量是完全有效的(這就是你在這里所做的,通過分配一個新值)。
最后,你的樣本不過是這樣的:
var x = 23;
x = 'foo';
這也將起作用, x
將是'foo'
,它的類型將是string
。 與您的示例的唯一區別是,在您的示例中,涉及function
類型的值。
除了其他答案之外,還應該注意的是,如果您以下列方式聲明您的函數:
var myName = function() {
console.log('Rich');
}
或者干脆
myName = function(){
console.log('Rich')
}
與“function myName . . .”語法相反,typeof myName 將返回“function”
2 年過去了,但也許它仍然與某人有關 您是對的,在解釋對象時確實如此:
掃描函數聲明的上下文
掃描變量聲明的上下文
但是,對於全局范圍而言,情況似乎並非如此。 即,當我定義一個對象時,輸出與它應該完全一樣,當我在全局范圍內定義相同時,它不是......仍然試圖圍繞這個
由於Hoisting
你的變量和函數定義被移到頂部,所以你有:
var myName;
// moved to top
function myName () {
console.log ("Rich");
}
// next your code
myName = "Richard";
console.log(typeof myName); // string
如果你像這樣重寫你的代碼:
var myName = "Richard"; // Variable assignment (initialization)
myName = function () { // Variable redefinition
console.log ("Rich");
}
console.log(typeof myName); // function
你的myName
變量現在是一個函數,因為只有myName
變量被hoisted
:
var myName;
myName = "Richard"; // Variable assignment (initialization)
myName = function () { // Variable redefinition
console.log ("Rich");
}
console.log(typeof myName); // outputs 'function'
“提升”的想法是一種理解正在發生的事情的糟糕方式。 換句話說,在我看來,“吊裝”是對吊裝的不好解釋。
真正發生的不是“提升”。 真正發生的是javascript分兩個階段執行代碼:編譯階段和評估階段。 javascript 社區稱此為“提升”的症狀,但大多數人無法理解為什么要提升提升,因為他們認為 javascript 解釋器具有稱為“提升”的此功能(他們沒有)。
實際發生的事情比起吊的想法更容易解釋。 規則是:
Javascript 總是自上而下地解析代碼。 它從不重新排序代碼(從不提升)。
執行有兩個階段:編譯和評估。
所有聲明都在編譯階段處理,在編譯階段不會評估任何表達式(因為“評估”事情是在評估階段完成的)。
在求值階段處理所有表達式和任何其他需要求值的內容。
記住規則 1,所有解析都是自上而下完成的,沒有回溯,沒有提升。
讓我們以您的示例為例,並通過牢記 javascript 的編譯和評估階段來嘗試理解它:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
在編譯階段,解釋器會看到你聲明了一個變量。 它為此變量分配一塊內存區域,並為其分配undefined
值。
在編譯階段,解釋器會看到你聲明了一個函數。 它還注意到函數名掩蓋了變量名。 因此它創建了一個函數“myName”(這意味着此時變量myName
指向該函數)。
編譯階段結束。 現在我們進入評估階段。
在評估階段,解釋器會看到您為myName
分配一個字符串。
當我們到達函數聲明時,沒有什么要評估的,因為聲明是在編譯階段處理的。
在評估階段,解釋器會看到你 console.logging typeof myName
。 由於分配給它的最后一個東西是一個字符串,它打印“字符串”。
請注意,如果您刪除字符串賦值,則myName
將是 typeof "function"。 那是因為在這種情況下,分配給它的最后一件事是聲明的函數。
有關由兩個執行階段引起的其他微妙之處,請參閱此相關問題: JavaScript 函數聲明和評估順序
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.