在Javascript中,函數和對象是交織在一起的。有些函數的特性與對象相關聯。這一點的內容在第六部分會討論到。
這一部分主要討論函數與其它比較熟悉的語言(如C/C++)不同的地方
5.1 函數定義
function 函數名(參數1,參數2...)
{
主體;
}
函數內可以有return,也可以沒有return. 沒有return時,函數返回undefined值。
另外,Javascript是類型寬鬆的語言,所以,對於函數調用時傳遞參數,有以下特性:
① Javascript不會檢測傳遞的資料是不是函數要求的類型。
如果參數的資料類型很重要,可以在函數內用typeof運算子進行檢測
② Javascript不會檢測傳遞給它的參數是否正確。
如果傳遞的參數比需求的個數多,多餘的值被忽略。
如果傳遞的參數比需求的個數少,所忽略的幾個參數被賦於undefined值
③ 函數內部有個Arguments對象維護著實際傳遞給函數的參數。
用它可以實現得到實際傳遞給函數的參數個數,及參數值。用於實現可變參數函數。
5.2 嵌套函數
實現如下:
1function hypotenuse(a, b) {
2 function square(x) { return x*x; }
3 return Math.sqrt(square(a) + square(b));
4}
5.3 函數參數
● 選擇性參數
因為不會檢測傳遞給它的參數是否正確,所以,可以忽略到相應的參數來達到選擇性參數的目的。
1function copyPropertyNamesToArray(o, /**//* optional */ a) {
2 if (!a) a = []; // If undefined or null, use a blank array
3 // 以上語句也可以這樣寫 a = a || [];
4 for(var property in o) a.push(property);
5 return a;
6}
● 可變參數
在一個函數體內,標識符arguments具有特殊含義。它是引用arguments對象的一個特殊屬性。
其類似一個數組的對象,可以按照數目擷取傳遞給函數的參數值。
arguments具有length屬性,可以獲得實際傳遞給函數的參數個數
取得第一個參數值,可以使用argments[0]來獲得。
1function max(/**//* */)
2{
3 var m = Number.NEGATIVE_INFINITY;
4 // Loop through all the arguments, looking for, and
5 // remembering, the biggest
6 for(var i = 0; i < arguments.length; i++)
7 if (arguments[i] > m)
8 m = arguments[i];
9 // Return the biggest
10 return m;
11}
arguments具有callee屬性,引用當前正在執行的函數。
arguments並非真正的數組,它是一個Arguments對象。
5.4 作為資料的函數
函數最重要的就是它們能夠定義和調用,定義和調用是Javascript和大多數程式語言的文法特性。
但是,在Javascript中,函數並不只是一種文法,其也可以作為資料來看待。這意味著,可以把函數賦給變數,儲存在對象的屬性或數組元素中,作為參數傳遞給函數等。
例1:函數賦值給變數:
1function square(x) { return x*x; }
2var a = square(4); // a contains the number 16
3var b = square; // Now b refers to the same function that square does
例2:儲存在對象的屬性或數組元素中
1var o = new Object;
2o.square = function(x) { return x*x; } // function literal
3y = o.square(16);
4var a = new Array(3);
5a[0] = function(x) { return x*x; }
關於這點,可以參考《Javascript權威指南》8.3節最後例舉的一個例子。
5.5 作為方法的函數及this關鍵字
對象的方法只不過是對象的一個屬性,且該屬性引用的是函數類型而已。
因為函數可以賦給任何變數,可以賦給一個對象的任何屬性。
1var calculator = { // An object literal
2 operand1: 1,
3 operand2: 1,
4 compute: function() {
5 this.result = this.operand1 + this.operand2;
6 }
7};
8calculator.compute(); // What is 1+1?
9print(calculator.result); // Display the result
以上,this關鍵字很重要,任何作方法的函數都被有效傳遞了一個隱式的參數,即調用函數的對象(this).
5.6 函數的屬性和方法
函數是Javascript對象的一種特殊類型,typeof運算子用於函數類型時會返回字串“function”
既然函數是對象,它就具有屬性和方法,就像其它的對象一樣。
● 屬性lenght
不同於函數體內arguments的length屬性,函數自身的length屬性是一個唯讀屬性,返回的是函數需要的實際參數數目。
● 定義函數自身的屬性,具有static屬性
1// Create and initialize the "static" variable.
2// Function declarations are processed before code is executed, so
3// we really can do this assignment before the function declaration.
4uniqueInteger.counter = 0;
5
6// Here's the function. It returns a different value each time
7// it is called and uses a "static" property of itself to keep track
8// of the last value it returned.
9function uniqueInteger() {
10 return uniqueInteger.counter++; // Increment and return our "static" variable
11}
● 方法 apply() 和 call()
這兩個方法可以像調用其它方法一樣調用函數。第一個參數都是要調用的函數對象,函數體內這一參數是關鍵字this的值。
call的剩餘參數是傳遞給要調用的函數的值。
to the function f() and invoke it as if it were a method of the object o, you could use code like this:
f.call(o, 1, 2);
This is similar to the following lines of code:
o.m = f;
o.m(1,2);
delete o.m;
The apply() method is like the call() method, except that the arguments to be passed to the function are specified as an array:
f.apply(o, [1,2]);
For example, to find the largest number in an array of numbers, you could use the apply() method to pass the elements of the array to the Math.max() function:
var biggest = Math.max.apply(null, array_of_numbers);