2015-07-10 41 views
5

雖然在我的整個生活中,我從來沒有遇到過這種情況,但我是否正確地認爲JavaScript必須在運行任何東西之前分配函數?是否定義了函數而與訂單無關?

在我所有的經驗中,我預計這會返回'undefined',但顯然它會返回'function'。

function bar() { 
    return foo; 
    foo = 10; 
    function foo() {} 
    var foo = '11'; 
} 
alert(typeof bar()); 

有人能爲我解釋這個嗎?

+0

[Javascript函數範圍和提升]的可能重複(http://stackoverflow.com/questions/7506844/javascript-function-scoping-and-hoisting) – DTing

+0

是的。在輸入[*執行上下文*](http://ecma-international.org/ecma-262/6.0/index.html#sec-execution-contexts)時,所有函數和變量聲明都將在任何代碼運行之前處理。 – RobG

回答

7

JavaScript的這種行爲被稱爲提升。對MDN有很好的解釋(https://developer.mozilla.org/en-US/docs/Glossary/Hoisting

在JavaScript中,函數和變量被掛起。提升是JavaScript將聲明移動到作用域頂部(全局作用域或當前函數作用域)的行爲。

這意味着您可以在聲明它之前使用函數或變量,換句話說:函數或變量可以在已被使用之後聲明。

基本上,如果聲明這樣一個變量:

console.log(s);    // s === undefined 
var s = 'some string'; 

s聲明將是「懸掛」到範圍的開始(即,會出現線路上無ReferenceErrorconsole.log)。 變量的值不會在那一刻被定義,雖然

這同樣與分配一個匿名函數的變量,所以:

console.log(f);    // f === undefined 
f();      // TypeError: f is not a function 
var f = function() {};  // assigning an anonymous function as a value 
f();      // ok, now it is a function ;) 

變量將被吊起,從而在整個範圍內可見,但它的價值,即使它是一個函數,將仍然未定義 - 因此如果您嘗試執行該錯誤。

在另一方面,如果你定義一個名爲功能

console.log(f);    // f === function f() 
f();      // we can already run it 
function f() {};   // named function declaration 

它的定義也將懸掛,所以你甚至可以在你已經宣佈它的範圍的第一行運行它。

+0

我真的不喜歡「提升」這個詞,它是一個用詞不當,引用的解釋很差。它推斷代碼是以某種方式移動的,但不是。真正的答案是,在任何代碼執行之前,函數和變量聲明都被*處理了。 – RobG

+0

精彩地解釋,謝謝你這清楚了這一點,我甚至不知道JavaScript做了嵌套函數,我認爲這只是根的範圍。傻我 –

+0

@RobG是的,公平點。這有點像我們對「自我調用功能」有一段時間了,不是嗎?我也不是粉絲(你應該聽聽它是如何翻譯成我的語言的,這更像是「提升」;))現在它是一個相當通用的術語,我認爲它更容易解釋,而不會涉及太多細節(甚至如果犧牲準確性) –

0

那麼在JavaScript函數中就是Object。

當你說的typeof巴(),在欄功能要返回是函數的另一function.You剛剛回國的名字,所以,它返回FOO的構造所以,你的類型的得到的值是foo的構造函數這是函數的類型。所以,它提醒函數。它仍然指的FOO因爲closure

再在酒吧認定中,要退,但它的定義仍然是不encountered.In的JavaScript時,在解析變量的指令,聲明和功能放在當前功能範圍的頂部。

所以, 你的發言

function bar() { 
    return foo; 
    foo = 10; 
    function foo() {} 
    var foo = '11'; 
} 

相當於

function bar() { 
    function foo() {} 
    return foo; 
    foo = 10; 

    var foo = '11'; 

這就是所謂的JavaScript top hoist

} 
0

這是很容易測試;

foo(1); 

function foo(i) { 
    if (bar()) { 
     alert("foo called, bar true, i = " + i); 
    }; 
} 

foo(2); 

function bar() { 
    return true; 
} 

foo(3); 

DEMO

這表明,加載的Javascript執行任何之前的所有功能。因此,定義哪些順序功能並不重要。

相關問題