本文地址:http://blog.163.com/jinlu_hz/blog/static/113830152201131132035178/
原文地址:http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
原文做者:ben cherry
在前篇小議javascript之全局對象建立譯文中提到過JavaScript Hoisting概念,當時不甚瞭解。google以後發現ben cherry解釋的最爲明瞭,因而有了本文這篇乾貨翻譯稿。
翻譯能力有限,辭不達意的地方請自動跳過或者直接閱讀原文。
——如下爲翻譯——
JavaScript Scoping and Hoisting(JavaScript中的做用域與變量聲明提高/聲明時機提高)
你知道下面JavaScript代碼的執行結果是什麼嗎?
javascript
foo = ; bar() (!foo) foo = ; alert(foo); bar();若是你對foo的值實際上爲"10"而感到詫異的話,再看一下下面這個例子:
a = ; b() a = ; ; a() b(); alert(a);
<stdio.h> main() { x = ; printf(, x); () { x = ; printf(, x); } printf(, x); }
if
語句中時,當前做用域中的新變量會被聲明,而且不會影響到外部做用域。但在JavaScript中狀況並非這樣:
x = ; console.log(x); (true) x = ; console.log(x); console.log(x);
if
語句中的代碼塊並不會建立新的做用域,只有函數纔會。
foo() x = ; (x) ( () x = ; ());這個函數很是靈活,不只僅在塊級語句內,須要時能在任何地方使用。然而我強烈建議你多花點時間來理解JavaScript的做用域。
語言級別:默認在所用做用域下會定義this
、arguments
html
傳入參數:函數命名的參數,做用域是當前函數體java
函數聲明:例如function foo() {}程序員
變量聲明:例如var foo;瀏覽器
//以上翻譯地比較晦澀,建議直接看原文
函數聲明與變量聲明常常被JavaScript引擎隱式地提高到當前做用域的頂部,也就是說:
ide
foo() bar(); x = ;實際上會被解釋成:
foo() x; bar(); x = ;也就是說,下面兩種聲明方式是等價的:
foo() (false) x = ; ; y = ; foo() x, y; (false) x = ; ; y = ;
test() foo(); bar(); foo = () alert(); bar() alert(); test();這個例子中,只有包含函數體的函數聲明會被提高聲明。foo雖然會被提高聲明,可是函數體卻在執行中被賦值。以上就是提高聲明時機的基本概念,看起來一點也不復雜。
原生變量arguments
特立獨行,包含了傳遞到函數中的參數。若是自定義以arguments
爲命名的參數,將會阻止原生arguments
對象的建立。因此勿使用arguments
爲名稱的參數。函數
胡亂使用this
標識符會引發語法錯誤。this
若是多個參數具備相同的命名,那麼最後一個參數會優先於先前的,即時這個參數未定義。google
Named Function Expressions(函數命名錶達式)
你能夠經過函數表達式給函數命名,語法上看起來像是函數聲明,實則不是。上一段代碼:
編碼
foo(); bar(); baz(); spam(); foo = () ; bar() ; baz = spam() ; foo(); bar(); baz(); spam();
foo(a, b, c) x = , bar, baz = ;