2014-09-29 67 views
1

我想擴展函數原型來返回函數的單例版本。在Function.prototype中訪問「this」不可能?

Function.prototype.once = function() { 
    var called = false, memo; 
    return function() { 
     console.log('AP', this); 
     if (!called) memo = this.apply(this, arguments); 
     called = true; 
     return memo; 
    } 
} 

控制檯記錄窗口對象。這是爲什麼!=當前功能?以及如何解決這個問題?

+2

快樂codewars :) – Florent 2014-09-29 13:28:38

回答

7

你不能「關閉了」 this,所以你需要要麼訴諸老var self = this招(即,獲得其中可以被關閉了一個變量this參考),或者簡單綁定你的功能:

return function() { 
    console.log('AP', this); 
    if (!called) memo = this.apply(this, arguments); 
    called = true; 
    return memo; 
}.bind(this); 
+1

'綁定'是正確的方法。我會接受你的回答。對不起,@Florent,但是meagar比你快1秒:) – 2014-09-29 13:30:19

+0

恕我直言,'.bind'是矯枉過正的,只有當你不控制被調用的函數範圍時才能使用它(例如,你可以關閉外部 - 變量變量)。當編寫一個簡單的嵌套函數時,通過別名的簡單閉包更有效。 – Alnitak 2014-09-29 17:58:45

4

當然,這是可能的,但你的內在功能創建一個新的上下文,所以它內部的this是不一樣的外部this

只需創建一個外部參考原來的功能:

Function.prototype.once = function() { 
    var f = this; // use 'f' in the inner function 
    ... 
} 

注:根據您的意圖,你也可以有同樣的問題與arguments

+0

你是對的。爲什麼我沒有這個。但我更喜歡'bind'的方法:) – 2014-09-29 13:31:04

+0

@BarthZalewski,你覺得'.bind'是如何工作的? ;-)另外,'.bind'具有創建一個額外的'function'的開銷,而不僅僅是關閉對'this'的額外引用。 – Alnitak 2014-09-29 14:44:36

+0

(有關更多信息,請查看https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind中的polyfill查看「.bind」有多少開銷) – Alnitak 2014-09-29 14:50:48

1

您必須綁定到匿名函數的上下文。

Function.prototype.once = function() { 
    var called = false, memo; 
    return (function() { 
    console.log('AP', this); 
    if (!called) memo = this.apply(this, arguments); 
    called = true; 
    return memo; 
    }).bind(this); 
} 
相關問題