1、一條函數聲明語句實際上聲明瞭一個變量,並把一個函數對象賦值給它。
2、函數聲明語句並非真正的語句,ECMAScript規範只是允許它們作爲頂級語句。它們可以出現在全局代碼裏,或者內嵌在其他函數中,但它們不能出現在循環、條件判斷,或者try/cache/finally以及with語句中。注意,此限制僅適用於以語句聲明形式定義的函數。函數定義表達式可以出現在JavaScript代碼的任何地方。
3、根據ECMAScript 3和非嚴格的ECMAScript5對函數調用的規定,調用上下文(this的值)是全局對象。然而,在嚴格模式下,調用上下文則是undefined。以函數形式調用的函數通常不使用this關鍵字。不過,“this”可以用來判斷當前是否是嚴格模式。
//定義並調用一個函數來確定當前腳本運行時是否爲嚴格模式
var strict = (function(){ return !this; }());
4、JavaScript,JScript,ECMAScript及對應瀏覽器的版本:
JavaScript |
JScript |
ECMAScript |
Release date |
Netscape Navigator |
Firefox |
IE |
Opera |
Safari |
Chrome |
||
1.0 |
1.0 |
|
March 1996 |
2.0 |
|
|
|
|
|
||
1.1 |
2.0 |
|
August 1996 |
3.0 |
|
3.0- later versions, January 1997 |
|
|
|
||
1.2 |
|
|
June 1997 |
|
|
|
|
|
|
||
1.3 |
3.0 |
ECMA-262 1st edition/ ECMA-262 2nd edition |
October 1998 |
4.06-4.7x |
|
4.0 -Oct 1997 |
|
|
|
||
1.4 |
4.0 |
|
|
|
|
|
|
|
|
||
|
5.0 |
|
March 1999 |
|
|
5.0 |
|
|
|
||
|
5.1 |
|
|
|
|
5.01 |
|
|
|
||
1.5 |
5.5 |
ECMA-262 3rd edition |
November 2000 |
6.0 |
1.0 |
5.5-July 2000 |
6.0-11.0 |
3.0-5 |
1.0-10.0.666 |
||
|
5.6 |
ECMA-262 3rd edition |
October 2001 |
|
|
6.0 |
|
|
|
||
|
5.7 |
ECMA-262 3rd edition + ECMA-327 (ES-CP) |
November 2006 |
|
|
7 |
|
|
|
||
|
5.8 |
|
March 2009 |
|
|
8 |
|
|
|
||
1.6 |
|
1.5 + Array extras + Array and String generics + E4X
|
November 2005 |
|
|
|
|
|
|
||
1.7 |
|
1.6 + Pythonic generators + Iterators + let
|
October 2006 |
|
2.0(Gecko 1.8.1) |
|
|
|
|
||
1.8 |
|
|
June 2008 |
|
3.0(Gecko 1.9) |
|
|
|
|
||
1.8.1 |
|
|
|
|
3.5 |
|
|
|
|
||
1.8.2 |
|
1.8.1 + Minor updates |
June 22, 2009 |
|
3.6 |
|
|
|
|
||
1.8.5 |
|
1.8.1 + ECMAScript 5 Compliance |
July 27, 2010 |
|
4 |
9 |
|
|
|
||
2.0 (work in progress) |
|
Harmony(work in progress) |
|
|
|
|
|
|
|
5、構造函數通常不使用return關鍵字,它們通常初始化新對象,當構造函數的函數體執行完畢時,它會顯式返回。在這種情況下,構造函數調用表達式的計算結果就是這個新對象的值。然而如果構造函數顯式地使用return有返回一個對象,那麼調用表達式的值就是這個對象。如果構造函數使用return語句但沒有指定返回值,或者返回一個原始值,那麼這時將忽略返回值,同時使用這個新對象作爲調用結果。
6、可以接收任意個數的實參的函數稱爲“不定實參函數”(varargs function)。注意,不定實參函數的實參個數不能爲零,arguments[]對象最適合的應用場景是在這樣一類函數中,這類函數包含固定個數的命名和必需參數,以及隨後個數不定的可選實參。
7、除了數組元素,實參對象還定義了callee和caller屬性。在ECMAScript5嚴格模式中,對這兩個屬性的讀寫操作都會產生一個類型錯誤。而在非嚴格模式下,ECMAScript標準規範規定callee屬性指代當前正在執行的函數。caller是非標準的,但大多數瀏覽器都實現了這個屬性,它指代調用當前正在執行的函數的函數。通過caller屬性可以訪問調用棧。Callee屬性在某些時候會非常有用,比如在匿名函數中通過callee來遞歸地調用自身。
var factorial = function(x){
if( x <= 1) return1;
return x *arguments.callee(x-1);
}
8、在函數中聲明的變量在整個函數體內都是可見的(包括在嵌套的函數中),在函數的外部是不可見的。不在任何函數內聲明的變量是全局變量,在整個JavaScript程序中都是可見的。在JavaScript中是無法聲明只在一個代碼塊內可見的變量的,基於這個原因,我們常常簡單地定義一個函數用做臨時的命名空間,在這個命名空間內定義的變量都不會污染到全局命名空間。
function mymodule(){
//模塊代碼
//這個模塊所使用的所有變量都是局部變量
//而不會污染全局命名空間
}
mymodule() //不要忘了還要調用這個函數
這段代碼僅僅定義了一個單獨的全局變量:名叫“mymodule”的函數。這樣還是太麻煩,可以直接定義一個匿名函數,並在單個表達式中調用它:
(function(){ //mymodule()函數重寫爲匿名的函數表達式
//模塊代碼
}()); //結束函數定義並立即調用它
Function之前的左圓括號是必需的,因爲如果不寫這個左圓括號,JavaScript解釋器會試圖將關鍵字function解析爲函數聲明語句。使用圓括號JavaScript解釋器纔會正確地將其解析爲函數定義表達式。
9、閉包是指函數變量可以被隱藏於作用域鏈之內,因此看起來是函數將變量“包裹”了起來。
10、函數定義時的作用域鏈到函數執行時依然有效。每次調用JavaScript函數的時候,都會爲之創建一個新的對象用來保存局部變量,把這個對象添加至作用域鏈中。當函數返回的時候,就從作用域鏈中將這個綁定變量的對象刪除。如果不存在嵌套的函數,也沒有其他引用指向這個綁定對象,它就會被當作垃圾回收掉。如果定義了嵌套的函數,每個嵌套的函數都各自對應一個作用域鏈,並且這個作用域鏈指向一個變量綁定對象。但如果這些嵌套的函數對象在外部函數中保存下來,那麼它們也會和所指向的變量綁定對象一樣當作垃圾回收。但是如果這個函數定義了嵌套的函數,並將它作爲返回值返回或者存儲在某處的屬性裏,這時就會有一個外部引用指向這個嵌套的函數。它就不會被當作垃圾回收,並且它所指向的變量綁定對象也不會被當作垃圾回收。如果使用不慎,閉包很容易造成“循環引用”,當DOM對象和JavaScript對象之間存在循環引用時需要格外小心,在某些瀏覽器下會造成內存泄漏。
11、關於Function()構造函數有幾點需要特別注意:
l Function()構造函數允許JavaScript在運行時動態地創建並編譯函數。
l 每次調用Function()構造函數都會解析函數體,並創建新的函數對象。如果是在一個循環或者多次調用的函數中執行這個構造函數,執行效率會受影響。相比之下,循環中的嵌套函數和函數定義表達式則不會每次執行時都重新編譯。
l 最後一點,也是關於Function()構造函數非常重要的一點,就是它所創建的函數並不是使用詞法作用域,相反,函數體代碼的編譯總是會在頂層函數(也就是全局作用域)執行。
12、不完全函數是一種函數變換技巧,即把一次完整的函數調用拆成毒刺函數調用,每次傳入的實參都是完整實參的一部分,每個拆分開的函數叫做不完全函數(partial function),每次函數調用叫做不完全調用(partial application),這種函數變換的特定是每次調用都返回一個函數,直到得到最終運行結果爲止,舉一個簡單的例子,將對函數f(1,2,3,4,5,6)的調用修改爲等價的f(1,2)(3,4)(5,6),後者包含三次調用,和每次調用相關的函數就是“不完全函數”。