標籤:prot type blog 自己的 cpm 綁定 另一個 world 經典
在JavaScript中,函數其實是對象,每個函數都是Function類的執行個體,既然函數對象,那麼就具有自己的屬性和方法,因此,函數名實際上也是一個指向函數對象的指標,不會與某個函數綁定。
一、函數的聲明
方式一:常規方式
1 function sum1(num1,num2){2 return num1+num2 3 }
方式二:函數運算式
1 var sum2=function(num1,num2){2 return num1+num2; 3 };
方式三:動態建立函數(這種方式用得不多)
1 var sum3=new Function("num1","num2","return num1+num2");//動態建立函數
測試:
1 <script type="text/javascript"> 2 function sum1(num1,num2){ 3 return num1+num2 4 } 5 var sum2=function(num1,num2){ 6 return num1+num2; 7 }; 8 var sum3=new Function("num1","num2","return num1+num2"); 9 //測試10 document.write("<pre>");11 document.writeln("sum1(1,2)="+sum1(1,2));12 document.writeln("sum2(1,2)="+sum2(1,2));13 document.writeln("sum3(1,2)="+sum3(1,2));14 document.write("</pre>");15 </script>
測試結果:
這裡順便提一下方式一和方式二這兩種函式宣告方式的區別,對於採用方式一聲明的函數,解析器會率先讀取函式宣告,並使其置於任何代碼之前;而對於函數運算式,則必須等到解析器執行到它所在的程式碼,才別執行。
可以用如下的代碼證明:
1 alert("sum1(1,2)="+sum1(1,2));//可以正常運行2 function sum1(num1,num2){3 return num1+num2 4 }5 alert("sum2(1,2)="+sum2(1,2));//錯誤:缺少對象6 var sum2=function(num1,num2){7 return num1+num2; 8 };二、函數重載
JavaScript沒有方法重載的說法,如果兩個方法名字一樣,即使參數個數不一樣,那麼後面定義的就會覆蓋前面定義,調用方法時永遠是調用後定義的那個。
用如下的代碼證明JavaScript不支援函數的重載:
1 <script type="text/javascript"> 2 function Test(a){ 3 alert(a); 4 } 5 function Test(a,b){ 6 alert("HelloWorld!"); 7 } 8 function Test(a,b){ 9 alert(a+" "+b);10 }11 12 Test(20);//調用的是最後定義的那個Test方法13 Test(30,50);//調用的是最後定義的那個Test方法14 </script>
把函數名想像成指標,這例子中聲明了三個同名函數,最後聲明的一個就會覆蓋了前面函數,用下面的寫法或許更好理解:
1 /*聲明一個變數Test,Test變數中存放了指向函數對象的指標(引用)*/ 2 var Test =function (a){ 3 alert(a); 4 } 5 6 /*將變數Test指向了另一個函數對象*/ 7 Test = function (a,b){ 8 alert("HelloWorld!"); 9 }10 /*將變數Test指向了另一個函數對象*/11 Test = function (a,b){12 alert(a+" "+b);13 }三、JavaScript函數的特殊性
JavaScript中的函數名本身就是變數,所以函數也可以當作普通變數來使用。也就是說,不僅可以像傳遞參數一樣把一個函數傳遞給另一個函數,而且可以將一個函數作為另一個函數的結果返回。
例如:在使用建構函式給一個對象初始化屬性時,指定函數屬性
1 <script type="text/javascript"> 2 function fn(num1,num2,oper){ 3 var result=-1; 4 switch(oper){ 5 case "+": 6 result=num1+num2; 7 break; 8 case "-": 9 result=num1-num2;10 break;11 case "*":12 result=num1*num2;13 break;14 case "/":15 result=num1/num2;16 break;17 }18 return result;19 }20 /*建立Person類*/21 function Person(name,age,fn){22 this.Name=name;23 this.Age=age;24 this.Fn=fn;//使用傳遞進來的fn函數為函數屬性Fn初始化25 }26 /*在使用建構函式給一個對象初始化屬性時,也可以指定函數屬性*/27 var p1 = new Person("孤傲蒼狼",24,fn);28 var retVal=p1.Fn(1,2,"+");29 alert(retVal);30 </script>
在函數內部,有兩個特殊的對象:arguments和this,arguments是一個數組對象,包含傳入的所有參數,arguments的主要作用是儲存函數參數,但這個對象還有個叫callee的屬性,該屬性是一個指向擁有這個arguments對象的函數。
1 //非常經典的遞迴函式 2 function factoriak(num){ 3 if(num<=1){ 4 return 1; 5 }else{ 6 return num * facaorial(num-1);//與函數名factoriak耦合性太高了 7 } 8 } 9 //上述代碼與函數名耦合性太高,一換函數名就不行了,就可以採用以下方法10 function factoriak(num){11 if(num<=1){12 return 1; 13 }else{14 return num * arguments.callee(num-1);//這樣無論用什麼名字都能完成遞迴調用 15 }16 }
this指的是函數執行時所處的範圍
每個函數都包含:length和prototype。length屬性工作表示函數希望接收的參數個數。
1 function sayName(name){ 2 alert(name); 3 } 4 function sum(num1,num2){ 5 return num1+num2; 6 } 7 function sayHi(){ 8 alert("hi"); 9 }10 alert("sayName函數接收的參數個數是:"+sayName.length);//111 alert("sum函數接收的參數個數是:"+sum.length); //212 alert("sayHi函數接收的參數個數是:"+sayHi.length);//0
每個函數都包含兩個非繼承而來的方法:apply()和call();這兩個方法的用途都是在特定的範圍中調用函數,實際上等於設定函數體內this對象的值
apply()方法接收兩個參數:一個是在其中運行函數的範圍,另一個是參數數組。其中第二個參數可以是Array的執行個體,也可以是arguments對象。
1 function sum(num1,num2){ 2 return num1+num2; 3 } 4 function callSum(num1,num2){ 5 return sum.apply(this,arguments); //傳入aguments對象 6 } 7 function callSum2(num1,num2){ 8 return sum.apply(this,[num1,num2]); //傳入數組 9 }10 alert(callSum(10,10)); //2011 alert(callSum2(10,10)); //20
call()方法接第一個參數是函數啟動並執行範圍,其餘的參數就是傳遞給函數運行時需要的參數(一個或多個)。
function sum(num1,num2){ return num1+num2;}function callSum(num1,num2){ return sum.call(this,num1,num2);}alert(callSum(10,10));
apply()和call()最強大的地方是能夠擴充函數賴以啟動並執行範圍
1 window.color="red";2 var o ={color:"blue"};3 function sayColor(){4 alert(this.color);5 }6 sayColor(); //red7 sayColor.call(this); //red8 sayColor.call(window); //red9 sayColor.call(o); //blue
JavaScript學習總結(十五)——Function類