2014-09-29 76 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); 
} 
相关问题