在ECMAScript中,Function(函數)類型實際上是對象。每個函數都是Function類型的實例,而且都與其他引用類型一樣具有屬性和方法。由於函數是對象,因此函數名實際上也是一個指向函數對象的指針。
1、三種函數聲明的方式
1》第一種:普通方式聲明函數
1 function box (num1,num2){
2 return num1+num2;
3 }
2》第二種:使用變量初始化的方式:
1 var box =function(num1,num2){
2 return num1+num2;
3 };
3》第三種:使用Function構造函數的方式
1 var box =new Function("num1",'num2','return num1+num2');
總結:第三種方式不推薦使用:因為要解析兩次代碼:第一次:解析常規的ECMAScript代碼,第二次是解析傳入構造函數中的字符串;所以影響性能。但是我們能從這種語法理解“函數是對象,函數名是指針”這個概念
2、作為值的函數
ECMAScript中的函數本身就是變量,所以函數也可以作為值來使用。也就是說,不僅可以傳遞參數一樣把一個函數傳遞進另一個函數,而且也可以將一個函數作為另一個函數的結果返回。類似於 c# 中的 委托,令方法 像參數一樣傳遞到另一個方法中。
復制代碼
1 function box(sum,num){//將函數 以參數的 形式 傳遞進 另一個函數
2 return sum(num); //將函數作為返回值 進行返回
3 }
4
5 function sum(num){
6 return num+10;
7 }
8 alert(box(sum,10));//20
復制代碼
3、函數內部的屬性
在函數內部,有兩個特殊的對象:arguments和this。arguments 是一個 類數組對象,包含著傳入函數中的所有參數,主要用途是保存函數參數,但這個對象還有一個名叫callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數。
arguments屬性的使用:
復制代碼
1 function box(){
2 alert(arguments.length);
3 for(var i=0;i
4 alert(arguments[i]); //取到每一個傳進來的參數
5 }
6 }
7
8 box(1,2,3,4);
復制代碼
callee屬性(是arguments的屬性)
復制代碼
1 //使用arguments.callee代替 自己
2 function sum(num){
3 if(num<=1){
4 return 1;
5 }
6 else{
7 return num * arguments.callee(num-1);
8 }
9 }
10 alert(sum(4));//24
復制代碼
this對象:
和c#中的this大致相似。this對象引用的是函數以執行操作的對象,或者說函數調用語句所處的那個作用域。
PS:當在全局作用域中調用函數時,this對象引用的就是window。
復制代碼
1 var color='紅色';
2 alert(window.color);//紅色 只要是全局作用域內的對象 就是 window下
3 alert(this.color)//紅色 this位於全局作用域下,this引用的就是window對象
4 alert(color);//紅色 可以省略 window直接輸出
5
6 window.color='藍色'; //等價於:var color='藍色';
7 alert(this.color);//藍色
8 alert(color);//藍色
復制代碼
this對象的經典的例子:
復制代碼
1 var box={
2 color:'紅色',
3 SayColor:function(){
4 alert(this.color); //this對象 指向的此作用域 范圍內的 對象的引用(就是box的引用)
5 }
6 };
7 box.SayColor();
8
9 window.color='紅色';
10 function SayColor(){
11 alert(this.color);//因為此方法位於 window下面,所以 方法內的this引用指向 window
12 }
13
14 SayColor();//紅色
15
16 var box={
17 color:'藍色的'
18 };
19 box.SayColor=window.SayColor; //賦值之後,SayColor中的this對象 指向 當前的 作用域 也就是 box對象
20 box.SayColor();//藍色的
復制代碼
4、匿名屬性和方法
ECMAScript中的函數式對象,因此函數也有屬性和方法。每個函數都含有兩個屬性:length和prototype。其中,length表示函數希望接收的命名參數的個數
PS:prototype屬性:它是保存所有實例方法的真正所在,也就是原型。這個屬性。我們將在面向對象一章詳細介紹。而prototype下有兩個方法:apply()和call(),每個函數都包含這兩個 非繼承 而來的方法。這兩個方法的用途都在特定的作用域中調用函數,實際上等於設置函數體內this對象的值
length屬性:
1 function sum(num1,num2){
2 return num1+num2;
3 }
4 alert(sum.length);
apply()方法:
復制代碼
1 function sum(num1,num2){
2 return num1+num2;
3 }
4
5 function num(num1,num2){
6 //第一個參數:此方法要執行的作用域(就是這個方法執行的作用域),第二個參數是 要傳遞到sum函數中的參數
7 return sum.apply(this,[num1,num2]); //參數數組[num1,num2]可以使用 arguments替換
8 }
9
10 alert(num(10,10));
復制代碼
call()方法:
call()方法執行的效果和apply是一樣的,不同之處是:他們之間傳遞參數的方式的不同
1 function box(num1,num2){
2 return sum.call(this,num1,num2);//從第二參數開始想函數內傳遞參數,而不是傳遞一個參數數組
3 //其實可以直接 調用函數,上面做法只是演示一下 apply 和call的用法
4 }
5
6 alert(box(1,2));
call()和apply()方法的真正的用武之地不是上面(因為上面實現沒意義),而是:改變方法的作用域,冒充方法的調用者進行調用方法,解決的是 對象之間的 “耦合”,降低了 耦合度
復制代碼
1 var color='紅色';
2
3 function SayColor(){
4 alert(this.color);
5 }
6 SayColor();//紅色
7
8 var box={
9 color:'藍色'
10 };
11
12 SayColor.call(box);//藍色 (改變了 方法的 作用域,但是沒有 使用 box.SayColor=SayColor;(耦合度太高了),降低了耦合度) 在運行call(box)方法的時候,SayColor()的運行環境已經變成了box對象裡了。
13 SayColor.call(this);//紅色
14 SayColor.call(window);//紅色
15
16 box.Say();
復制代碼
call()和apply()方法的最大好處:擴充作用域,並且 對象和方法之間不用發生任何的 耦合 關系