1、概述
- 函數聲明
- 采用函數表達式聲明函數時,function命令后面不帶有函數名。如果加上函數名,該函數名只在函數體內部有效,在函數體外部無效。
var print = function x(){ console.log(typeof x); }; x // ReferenceError: x is not defined
-
- 這種寫法的用處有兩個,一是可以在函數體內部調用自身,二是方便除錯。
- 函數名提升
- JavaScript 引擎將函數名視同變量名,所以采用function命令聲明函數時,整個函數會像變量聲明一樣,被提升到代碼頭部。
- 如果像下面例子那樣,采用function命令和var賦值語句聲明同一個函數,由於存在函數提升,最后會采用var賦值語句的定義。
var f = function () { console.log('1'); } function f() { console.log('2'); } f() // 1
2、函數的屬性和方法
- length屬性
- 函數的length屬性返回函數預期傳入的參數個數,即函數定義之中的參數個數。
function f(a, b) {} f.length // 2 // 上面代碼定義了空函數f,它的length屬性就是定義時的參數個數。不管調用時輸入了多少個參數,length屬性始終等於2。 // length屬性提供了一種機制,判斷定義時和調用時參數的差異,以便實現面向對象編程的“方法重載”(overload)。
- toString()
- 函數的toString()方法返回一個字符串,內容是函數的源碼。
3、函數作用域
- 定義
- 作用域(scope)指的是變量存在的范圍。在 ES5 的規范中,JavaScript 只有兩種作用域:一種是全局作用域,變量在整個程序中一直存在,所有地方都可以讀取;另一種是函數作用域,變量只在函數內部存在。ES6 又新增了塊級作用域。
- 注意,對於var命令來說,局部變量只能在函數內部聲明,在其他區塊中聲明,一律都是全局變量。
- 函數內部變量提升
- 與全局作用域一樣,函數作用域內部也會產生“變量提升”現象。var命令聲明的變量,不管在什么位置,變量聲明都會被提升到函數體的頭部。
- 函數本身作用域
- 函數本身也是一個值,也有自己的作用域。它的作用域與變量一樣,就是其聲明時所在的作用域,與其運行時所在的作用域無關(詞法作用域)。
var a = 1; var x = function () { console.log(a); }; function f() { var a = 2; x(); } f() // 1
4、參數
- 參數的省略
- 函數參數不是必需的,JavaScript 允許省略參數。
function f(a, b) { return a; } f(1, 2, 3) // 1 f(1) // 1 f() // undefined f.length // 2 // 沒有辦法只省略靠前的參數,而保留靠后的參數。如果一定要省略靠前的參數,只有顯式傳入undefined。
- 傳遞方式
- 函數參數如果是原始類型的值(數值、字符串、布爾值),傳遞方式是傳值傳遞(passes by value)。這意味着,在函數體內修改參數值,不會影響到函數外部。
var p = 2; function f(p) { p = 3; } f(p); p // 2 // 上面代碼中,變量p是一個原始類型的值,傳入函數f的方式是傳值傳遞。因此,在函數內部,p的值是原始值的拷貝,無論怎么修改,都不會影響到原始值。
-
- 如果函數參數是復合類型的值(數組、對象、其他函數),傳遞方式是傳址傳遞(pass by reference)。也就是說,傳入函數的原始值的地址,因此在函數內部修改參數,將會影響到原始值。
var obj = { p: 1 }; function f(o) { o.p = 2; } f(obj); obj.p // 2
-
- 如果函數內部修改的,不是參數對象的某個屬性,而是替換掉整個參數,這時不會影響到原始值。
var obj = [1, 2, 3]; function f(o) { o = [2, 3, 4]; } f(obj); obj // [1, 2, 3] // 這是因為,形式參數(o)的值實際是參數obj的地址,重新對o賦值導致o指向另一個地址,保存在原地址上的值當然不受影響。
- 同名參數
- 如果有同名的參數,則取最后出現的那個值;即使后面的a沒有值或被省略,也是以其為准。
function f(a, a) { console.log(a); } f(1, 2) // 2 function f(a, a) { console.log(a); } f(1) // undefined
- arguments對象
- 定義
- 正常模式下,arguments對象可以在運行時修改。
- 嚴格模式下,arguments對象與函數參數不具有聯動關系。也就是說,修改arguments對象不會影響到實際的函數參數。
- 與數組的關系
- 它是類似數組的對象,可轉換為數組。
- 定義
