2015-12-01 73 views
2

上我與封閉的工作方式在這個代碼有點糊塗:關閉對象

function Spy(target, method) { 
    var result = {count: 0}, 
     oldFn = target[method]; 
    target[method] = function(input) { 
     result.count++; 
     return oldFn.apply(target, arguments); 
    } 
    return result; 
} 

所以,當你指定這一個變量像

var logSpy = Spy(console, 'log') 

logSpy是與對象計數屬性。如果你打電話給console.log,被覆蓋的函數會增加result.count的值,但是它所訪問的結果是封閉的,對嗎?那麼封裝對象和全局logSpy對象之間的鏈接如何?我猜測logSpy對象正在引用封閉對象,因爲對象是通過引用傳遞給變量的?那麼logSpy作爲一個對象在技術上不存在於全局執行上下文中,而僅僅是對閉包的引用?

+0

我認爲這是正確的 - 在閉包中定義一個函數可以讓該函數訪問該閉包中的所有變量。我只能從經驗中發言,但是,我不知道JS的內部運作。 –

+0

「在JavaScript中,函數對象本身包含一個指向包含來自其聲明範圍的變量的對象的不可訪問屬性。」 [鏈接](https://lostechies.com/derekgreer/2012/02/17/javascript-closures-explained/) – xersiee

回答

1

當您撥打Spy(console, 'log')時,它會做4件事。

  1. 創建result對象。
  2. oldFn設置爲(參照)console.log(或更確切地說console['log'])。
  3. console['log']設置爲在resultoldFn附近「關閉」的新函數。
  4. 退貨(參考)result

那麼,發生了什麼是console.log現在是一個功能,但resultoldFn仍然存在於內存 - 他們沒有收集垃圾,但 - 因爲在這個新功能對它們的引用。

當你調用console.log它更新result對象的count屬性(你必須爲logSpy參考),然後調用「備份」 oldFn功能與正確的上下文/參數。