2010年9月13日 星期一

JS匿名函數

Javascript代碼


  1. "alert('http://www.k686.com/');">  
  2.   "text/javascript">  
  3. void function() {  
  4.    alert('k686绿色软件');  
  5. }();  
  6.   
  7.  
還可以寫成:
Javascript代碼



  1. "alert('http://www.k686.com/');">  
  2.   "text/javascript">  
  3. (function() {  
  4.    alert('k686绿色软件');  
  5. })();  
  6.   
  7.  


從以上例子中可以看出,js匿名函數的執行是在 onload 之前,那麼空函數是否可以取代onload的動作?

js匿名函數的寫法還有n多種.
顧名思義,匿名函數就是沒有實際名字的函數。例如,我們把上面的例子中,函數的名字去掉,再判斷一下他是不是一個函數:
複製代碼 代碼如下:
alert(typeof function(){});// "function"
alert(typeof function(x,y){return x+y;});// "function"
alert(typeof new Function("x","y","return x*y;"))// "function"
alert(typeof function(){});// "function" alert(typeof function(x,y){return x+y;});// "function" alert(typeof new Function("x","y","return x*y;"))// "function"

我們可以很容易地看到,它們全都是Function對象,換言之,他們都是函數,但是他們都有一個特點——沒有名字。所以我們把他們稱作「匿名函數」。然而,正因為他們沒有「名字」,我們也沒有辦法找到他們。這就引申了如何去調用一個匿名函數的問題了。
匿名函數的調用
要調用一個函數,我們必須要有方法定位它,引用它。所以,我們會需要幫它找一個名字。例如:
複製代碼 代碼如下:
var abc=function(x,y){
return x+y;
}
alert(abc(2,3)); // "5"
var abc=function(x,y){ return x+y; } alert(abc(2,3)); // "5"

上面的操作其實就等於換個方式去定義函數,這種用法是我們比較頻繁遇到的。例如我們在設定一個DOM元素事件處理函數的時候,我們通常都不會為他們定名字,而是賦予它的對應事件引用一個匿名函數。
對匿名函數的調用其實還有一種做法,也就是我們看到的jQuery片段——使用()將匿名函數括起來,然後後面再加一對小括號(包含參數列表)。我們再看一下以下例子:
複製代碼 代碼如下:
alert((function(x,y){return x+y;})(2,3));// "5"
alert((new Function("x","y","return x*y;"))(2,3));// "6"
alert((function(x,y){return x+y;})(2,3));// "5" alert((new Function("x","y","return x*y;"))(2,3));// "6"

很多人或許會奇怪,為什麼這種方法能成功調用呢?覺得這個應用奇怪的人就看一下我以下這段解釋吧。
大家知道小括號的作用嗎?小括號能把我們的表達式組合分塊,並且每一塊,也就是每一對小括號,都有一個返回值。這個返回值實際上也就是小括號中表達式的返回值。所以,當我們用一對小括號把匿名函數括起來的時候,實際上小括號對返回的,就是一個匿名函數的Function對象。因此,小括號對加上匿名函數就如同有名字的函數般被我們取得它的引用位置了。所以如果在這個引用變量後面再加上參數列表,就會實現普通函數的調用形式。
不知道以上的文字表述大家能不能看明白,如果還是理解不了的話,再看一下以下的代碼試試吧。
複製代碼 代碼如下:
var abc=function(x,y){return x+y;};// 把匿名函數對像賦給abc
// abc的constructor就和匿名函數的constructor一樣了。也就是說,兩個函數的實現是一樣的。
alert((abc).constructor==(function(x,y){return x+y;}).constructor);
var abc=function(x,y){return x+y;};// 把匿名函數對像賦給abc // abc的constructor就和匿名函數的constructor一樣了。也就是說,兩個函數的實現是一樣的。 alert((abc).constructor==(function(x,y){return x+y;}).constructor);

PS:constructor是指創建對象的函數。也就是函數對像所代表的函數體。
總之,將其(被小括號包含的匿名函數)理解為括號表達式返回的函數對象,然後就可以對這個函數對像作正常的參數列表調用了。(前面這裡犯了個錯 誤,只有函數表達式還是不能直接調用函數的,去掉匿名函數括號必須要伴隨將表達式賦值。也就是(function(){alert(1)})()應該是與 a=function(){alert(1)}()等價,不能連a=都去掉。)


以上轉載自 http://tuzwu.javaeye.com/blog/758499

3 則留言:

  1. 補充一下

    (function(){alert(1); })()
    相当于定义function获得函数的引用(表达式的返回值)再进行()运算

    回覆刪除
  2. function(){alert(1); }() 优先级高于 =

    = 的优先级原因


    function(){alert(1); }()
    变成了

    (function(){alert(1);}( ));

    回覆刪除