【JavaScript】Function型別是物件

00潤物無聲00發表於2015-11-15

    在ECMAScript中,Function(函式)型別是物件。每個函式都是Function型別的例項,而且都與其他引用型別一樣具有屬性和方法。因為函式是物件,所以函式名實際上也是一個指向函式物件的指標;

一.函式有三種宣告的方式:

    1.普通的宣告
    2.使用變數初始化函式
    3.使用Function建構函式;    因為function是物件所以可以使用New來構造,但是這樣的語法會導致解析兩次程式碼,影響心梗,所以不推薦使用;

二.作為值的函式

    ECMAScript中的函式名本身就是變數,所以可以作為值來使用。

    1.可以像傳遞引數一樣把一個函式傳遞給另一個函式,

    2.可以將一個函式作為另一個函式的結果返回;(下面例子說明)

<span style="font-family:SimSun;font-size:18px;"><span style="font-family:SimSun;font-size:18px;">    function box(someFunction,num)
    {
	    return someFunction(num); //someFunction
    }
    function sum(num)
    {
	return num+10;
    }

var result = box(sum,10);  //傳遞函式到另一個函式裡;sum函式作為引數,傳遞到box函式中。
alert(result);</span></span>


三.函式內部屬性;

在函式內部,兩個特殊物件:arguments 和 this 。
arguments物件;
    arguments:一個類陣列物件,包含傳入函式中的所有引數,用途是儲存函式引數;(apply和call的例子中體現)
    arguments物件有一個callee的屬性,該屬性是一個指標,指向擁有該arguments物件的函式;
    在使用遞迴演算法時,函式內部會呼叫自身,那麼函式內部就會用到函式的名字,一旦函式名字發生變化則內部函式名也需要進行修改,但是如果在函式內部,能夠用一個物件標識自身,那麼就不會隨著函式名字的變化而變化。

    arguments.callee代替函式名稱來解決這個問題;
<span style="font-family:SimSun;">    function box(num)
    {
	if(num<=1)
	{
		return 1;
	}
	else 
	{
		return arguments.callee(num-1);    //此處的arguments.callee代表box這個函式名稱,
                                   //但是當box函式名稱變化的時候,這裡不用變化,仍然表示該函式;
	}
    }</span>


this物件:
    引用的是函式據以執行操作的物件,或者函式呼叫語句所處的作用域;在全域性作用域中呼叫函式時,this物件引用window。
<span style="font-family:SimSun;font-size:18px;">    window.color = '紅色的';        //color是全域性的,所用this 物件引用的是window;
    alert(this.color);   

    var box = {
	color:'藍色的',             //區域性的color;
	sayColor:function(){
	alert(this.color); //此時的this指box裡的color; 
		           //sayColor這個函式是box物件的函式;this引用的是函式據以執行操作的物件box; 
	}
	
    };

    box.sayColor();					//藍色的;
    alert(this.color);              //此處this,依然是window所以是紅色的;</span>


四.函式屬性和方法
    ECMAScript中函式時物件,所有有屬性和方法。每個函式都包含兩個屬性;length 和 prototype。
length:函式希望接收的命名引數的個數;
prototype:它是儲存所有例項方法的真正所在, 即原型;這個屬性是一個物件,包含可以有特定型別的所有例項共享的屬性和方法;prototype是一個物件,它有兩個方法apply() 和 call(),每個函式都有這兩個非繼承而來的方法;
    apply()和call()都在特定的作用域中呼叫函式,實際上是設定函式體內this物件的值;

<span style="font-family:SimSun;font-size:18px;">    function box(num1, num2) {
        return num1 + num2; //原函式
    }
    function sayBox(num1, num2) {
        return box.apply(this, [num1, num2]); //this 表示作用域,這裡是 window    第一個引數是作用域;
    }                                         //[]表示 box 所需要的引數
    function sayBox2(num1, num2) {
        return box.apply(this, arguments);       //arguments 物件表示 box 所需要的引數 
    }
    alert(sayBox(10,10)); //20
    alert(sayBox2(10,10)); //20</span>

    call()和apply()相同,區別只是接收引數的方式不同;第一個引數是作用域,其它的引數都是直接給函式;

    apply() 和 call()最常使用的是能夠擴充套件函式執行的作用域;
<span style="font-family:SimSun;font-size:18px;">    var  color = '紅色的'

    var box = {
	    color:'藍色的'
    }

    function sayColor()
    {
	    alert(this.color);
    }

    sayColor();             //作用域在window;
    sayColor.call(this)     //作用域在window;
    sayColor.apply(this)    //作用域在window;
    sayColor.call(box)      //作用域在box;
    sayColor.apply(box)     //作用域在box;</span>

    apply() 和 call()來擴充作用域的最大的好處,是物件不需要與方法發生任何耦合關係;

總結:
    學習是一個重複的過程,反覆的運用,不斷的總結,第一次不理解沒關係,再學習一遍,跟同行交流一下,在實踐中運用,這樣的成長會更加深刻。

相關文章