2010-04-28 220 views
0

我想了解一些已經用於返回函數的變量。 這是示例代碼JS函數返回另一個函數

Prototype = {} 

Prototype.F = 
{ 
    bind: function() 
    { 
    var args = arguments, __method = args.shift(), object = args.shift(); 
    return function() 
    { 
     return __method.apply(object, args.concat(arguments)); 
    } 
    } 
} 

function ObjectA() 
{ 
    ... 
    this.addListener = Prototype.F.bind(this.eventSource.addListener, 
     this.eventSource); 
    ... 
} 


var a = ObjectA(); 
a.addListener(this); // assuming 'this' here will point to some window object 

據我瞭解在綁定返回()函數不計算直到它被稱爲在最後一行。可以接受。所以addListener將包含一個包含'apply'的函數體。

但是,我不明白,當addListener被調用時,它會有什麼樣的參數?特別是_methodargs將始終未初始化?

+0

'F'是一個函數,它在一個名爲'bind'的屬性(寫成對象字面值)上,它是一個返回函數的函數。 – RoToRa 2010-04-28 13:46:34

+0

對不起,錯字,我會更新。當然,我會結合。 – Pablo 2010-04-28 13:51:21

回答

1

的功能bind回報是closure在參數給bind功能,所以__method參數將是第一個參數bind(在你的榜樣通話,這將是this.eventSource.addListener功能)。

閉包基本上是具有內在綁定數據的函數。這裏有一個簡單的例子:

function makeAlert(msg) { 
    return function() { 
     alert(msg); 
    } 
} 
var myalert = makeAlert("Hi there!"); 
myalert(); // Alerts "Hi there!" 

通過makeAlert返回的功能「關閉了」(保留訪問)範圍的事情,創造了它,包括msg參數的makeAlert函數調用中。這就是爲什麼當我們稍後調用該函數時,即使對makeAlert的調用早已完成,它仍然有msgMore about closures here.

要記住關閉一個關鍵的事情是,他們保留一切這是在哪裏範圍內他們定義,不只是他們他們顯然是在利用的東西訪問。因此,例如:

function init() { 
    var data; 

    data = /* ...build some really big array of data...*/; 

    document.getElementById('foo').onclick = function() { 
     this.style.display = "none"; 
    }; 
} 

即使該事件處理程序無關的大數據陣列,它保持對它的引用,因此保持在調用init後,內存中的數據已經完成。這是因爲它所具有的鏈接是一個幕後對象(鬆散地稱爲「變量對象」),它是所有參數和局部變量的容器,它們在其定義的範圍內。 (在這種情況下,如果你不需要所有的數據,只需在末尾設置dataundefined。事件處理程序仍然會引用data,但該引用不再保存數組,所以數組的內存可以被回收。)

+0

所以換句話說,如果js引擎會檢測將來可能使用的任何函數,它將保存後續使用的範圍,所以無論何時何時調用它,該函數都可以有一定的工作範圍,並且已經決定了由js設計師,範圍是功能已被創建。只是想知道這個範圍是不可改變的?例如,我可以在內部函數中取消定義'data'?而且,通過訪問範圍從其他地方取消定義'data'? – Pablo 2010-04-28 15:46:06

+0

@Michael:像Javascript中的所有對象一樣,變量對象將被垃圾回收,如果沒有引用它的話;該函數是一個引用變量對象的對象,它保持變量對象不被GC化。只要某些東西具有對該函數的引用,就會使該函數不被GC調用,從而使該變量對象不被GC化。你明白了。 :-)變量對象中的(屬性名稱)內容由代碼確定;那些指向的東西可以像其他任何東西一樣改變,通過給它們賦值。所以(繼續) – 2010-04-28 18:45:57

+0

@Michael :(繼續)所以如果你想要數據指向的數組,但只有一次,你可以在第一次使用內部函數時給它賦值undefined。或者,更有用的是,如果(例如)在外部函數中有'count'成員,則可以在內部函數中增加它。像這樣的東西。 (查看我博客上的鏈接文章以獲取更多信息。) – 2010-04-28 18:47:18

0

_method和args將總是被初始化,因爲你定義它們,當你第一次調用

this.addListener = Prototype.F.bind(this.eventSource.addListener, this.eventSource); 

在那裏,你會得到_method將是this.eventSource.addListener,和args會成爲那兩個論點。

0

在功能範圍內,arguments是一個類似數組的對象,它包含調用函數時提供的值,而不管函數定義是否定義了參數。

所以本次通話:

Prototype.F.bind(this.eventSource.addListener, this.eventSource); 

導致此:

var args = arguments, __method = args.shift(), object = args.shift(); 

arguments包含2項:任何this.eventSource.addListenerthis.eventSource點,當函數被調用。將2個項目的集合複製到參數中,然後將項目從集體移動到__methodobject

由於調用bind實際上會生成另一個函數,因此新函數中的arguments實例將會不同 - 它將具有在該調用時提供的參數。來自呼叫的原始argumentsbind保存在args中,並與來自後面的函數調用的arguments組合。

相關問題