JavaScript的Function類型

ECMAScript的函數是對象,函數名是指針數組

建立:瀏覽器

函數聲明法:安全

   
   
            
   
   
  1. function sum (num1, num2) {  
  2.     return num1 + num2;  

函數表達式法:app

  
  
           
  
  
  1. var sum = function(num1, num2) {  
  2.     return num1 + num2;  
  3. }; 

函數表達式法:這種不推薦,由於這種語法會致使解析兩次代碼(第一次解析常規ECMAScript代碼,第二次解析傳入構造函數中的字符串),從而影響性能ide

  
  
           
  
  
  1. var sum = new Function("num1""num2""return num1 + num2");   //不推薦 

同時使用函數聲明和函數表達式:這種語法會在Safari出錯函數

  
  
           
  
  
  1. var sum = function sum () {} 

因爲函數名只是指針,因此以下:性能

 

  
  
           
  
  
  1. function sum(num1, num2){  
  2.     return num1 + num2;  
  3. }          
  4. alert(sum(10,10));         //20  
  5.           
  6. var anotherSum = sum;          
  7. alert(anotherSum(10,10));  //20  
  8.           
  9. sum = null;          
  10. alert(anotherSum(10,10));  //20 

函數名是指針,因此沒有重載:this

 

  
  
           
  
  
  1. function addSomeNumber (num) {  
  2.     return num + 100;  
  3. }  
  4.  
  5. function addSomeNumber (num) {  
  6.     retrun num + 200;  
  7. }  
  8.  
  9. var result = addSomeNumber(100); //300 

上面代碼其實是:spa

  
  
           
  
  
  1. function addSomeNumber (num) {  
  2.     return num + 100;  
  3. }  
  4.  
  5. addSomeNumber = function (num) {  
  6.     retrun num + 200;  
  7. }  
  8.  
  9. var result = addSomeNumber(100); //300 

建立第二個函數時,改變了addSomeNumber的指向prototype

函數聲明與函數表達式的一個區別:

解析器會率先讀取函數聲明,並使其在執行任何代碼前可用;而函數表達式,必須等到解析器執行到所在行,才能被解釋執行

  
  
           
  
  
  1. alert(sum(10,10));              //20  
  2.       
  3. function sum(num1, num2){  
  4.     return num1 + num2;  

若是改爲以下,就會報錯

  
  
           
  
  
  1. alert(sum(10,10));              //causes an error  
  2.       
  3. var sum = function(num1, num2){  
  4.     return num1 + num2;  
  5. };  

把函數當值使用:

將一個函數做爲另外一個函數的結果返回

  
  
           
  
  
  1. function callSomeFunction(someFunction, someArgument){  
  2.     return someFunction(someArgument);  
  3. }  
  4.  
  5. function add10(num){  
  6.     return num + 10;  
  7. }  
  8.           
  9. var result1 = callSomeFunction(add10, 10);  
  10. alert(result1);   //20  
  11.           
  12. function getGreeting(name){  
  13.     return "Hello, " + name;  
  14. }  
  15.           
  16. var result2 = callSomeFunction(getGreeting, "Nicholas");  
  17. alert(result2);   //Hello, Nicholas 

從一個函數中返回另外一個函數,如給對象數組排序:(默認狀況下,sort()會調用toString()方法)

  
  
           
  
  
  1. function createComparisonFunction(propertyName) {  
  2.           
  3.     return function(object1, object2){  
  4.         var value1 = object1[propertyName];  
  5.         var value2 = object2[propertyName];  
  6.           
  7.         if (value1 < value2){  
  8.             return -1;  
  9.         } else if (value1 > value2){  
  10.             return 1;  
  11.         } else {  
  12.             return 0;  
  13.         }  
  14.     };  
  15. }  
  16.  
  17. var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];  
  18.           
  19. data.sort(createComparisonFunction("name"));  
  20. alert(data[0].name);  //Nicholas  
  21.           
  22. data.sort(createComparisonFunction("age"));  
  23. alert(data[0].name);  //Zachary   

函數內部屬性:

函數內部有兩個特點的對象 arguments 和 this

arguments:是一個類數組對象,包含傳入函數的全部參數

callee:是arguments的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數

下面是一個經典的階乘例子:

  
  
           
  
  
  1. function factorial(num){  
  2.     if (num <= 1) {  
  3.         return 1;  
  4.     } else {  
  5.         return num * arguments.callee(num-1)  
  6.     }  
  7. }  
  8.  
  9. var trueFactorial = factorial;  
  10.           
  11. factorial = function(){  
  12.     return 0;  
  13. };  
  14.           
  15. alert(trueFactorial(5));   //120  
  16. alert(factorial(5));   //0 

this:引用的是函數據以執行的環境對象(當在網頁的全局做用域中調用函數時,this對象引用的就是window)

  
  
           
  
  
  1. window.color = "red";  
  2. var o = { color: "blue" };  
  3.           
  4. function sayColor(){  
  5.     alert(this.color);  
  6. }  
  7.           
  8. sayColor();     //red  
  9.           
  10. o.sayColor = sayColor;  
  11. o.sayColor();   //blue 

caller:這個屬性中保存着調用當前函數的函數的引用,若是在全局做用域中調用當前函數,它的值爲null(Opera9.6版以前不支持該屬性)

  
  
           
  
  
  1. function outer(){  
  2.     inner();  
  3. }  
  4.           
  5. function inner(){  
  6.     alert(inner.caller);  
  7. }  
  8.           
  9. outer();              //function outer(){  
  10.                       //    inner();  
  11.                       //} 

下面這種寫法與上面同理,只是達到了更好的鬆耦合,這樣函數名稱能夠變更而不用改變內部代碼

  
  
           
  
  
  1. function outer(){  
  2.     inner();  
  3. }  
  4.           
  5. function inner(){  
  6.     alert(arguments.callee.caller);  
  7. }  
  8.           
  9. outer();              //function outer(){  
  10.                       //    inner();  
  11.                       //} 

注意:

1.這嚴格模式下,訪問 arguments.callee 會致使錯誤。

2.ECMAScript5 還定義了 arguments.caller 屬性,但在嚴格模式下也會致使錯誤,而在非嚴格模式下這個屬性始終是undefined。定義這個屬性是爲了分清 arguments.caller 和 函數的caller屬性。以上都是爲了增強這門語言的安全性,這樣第三方代碼就不會在相同的環境裏窺視其餘代碼了。

3.在嚴格模式下,不能給函數的caller屬性賦值,不然會出錯。

函數屬性和方法:

因爲在ECMAScript中,函數是對象,因此函數有屬性和方法

length:表示函數但願接收的命名參數的個數

  
  
           
  
  
  1. function sayName(name){  
  2.     alert(name);  
  3. }        
  4.           
  5. function sum(num1, num2){  
  6.     return num1 + num2;  
  7. }  
  8.           
  9. function sayHi(){  
  10.     alert("hi");  
  11. }  
  12.           
  13. alert(sayName.length);  //1  
  14. alert(sum.length);      //2  
  15. alert(sayHi.length);    //0 

prototype:第6章

apply():用途是在特定的做用域中調用函數,實際上等於設置函數體內this對象的值

需傳入2個參數:該運行函數的做用域(this)、參數數組

  
  
           
  
  
  1. function sum(num1, num2){  
  2.     return num1 + num2;  
  3. }  
  4.           
  5. function callSum1(num1, num2){  
  6.     return sum.apply(this, arguments);  //因爲在全局做用域中調用的,因此this指的是window對象  
  7. }  
  8.           
  9. function callSum2(num1, num2){  
  10.     return sum.apply(this, [num1, num2]);  
  11. }  
  12.           
  13. alert(callSum1(10,10));   //20  
  14. alert(callSum2(10,10));   //20 

注意:在嚴格模式下,未指定環境對象而調用函數,則this值不會轉型爲window。除非明確把函數添加到某個對象 或者 調用apply()或call(),不然this值將是undefined

call():用途是在特定的做用域中調用函數

傳入參數:該運行函數的做用域(this)、逐一列出參數

  
  
           
  
  
  1. function sum(num1, num2){  
  2.     return num1 + num2;  
  3. }  
  4.           
  5. function callSum(num1, num2){  
  6.     return sum.call(this, num1, num2);  
  7. }  
  8.           
  9. alert(callSum(10,10));   //20 

apply()和call()真正的用武之地是擴充函數賴以運行的做用域,以下:

  
  
           
  
  
  1. window.color = "red";  
  2. var o = { color: "blue" };  
  3.           
  4. function sayColor(){  
  5.     alert(this.color);  
  6. }  
  7.           
  8. sayColor();             //red  
  9.           
  10. sayColor.call(this);    //red  
  11. sayColor.call(window);  //red  
  12. sayColor.call(o);       //blue 

使用apply()或call()來擴充做用域的最大的好處,就是對象不須要與方法有任何耦合關係(這跟以前那個版本比(講this時),省下不少多餘的步驟)

bind():把this值與該函數綁定

  
  
           
  
  
  1. window.color = "red";  
  2. var o = { color: "blue" };  
  3.                              
  4. function sayColor(){  
  5.     alert(this.color);  
  6. }  
  7. var objectSayColor = sayColor.bind(o);  
  8. objectSayColor();      //blue 

把o與objectSayColor的this綁定,因此調用時返回的是blue,而不是red,第22章

支持bind()的瀏覽器有IE9+、Firefox 4+、Chrome……

每一個函數繼承的toLocaleString()、toString()、valueOf()都返回的函數的代碼,因瀏覽器而異。

相關文章
相關標籤/搜索