背景
我想要一个跟踪自己状态的函数:
var myObject = {
myFunction: function () {
var myself = this.myFunction;
var firstTime = Boolean(!myself.lastRetry);
if (firstTime) {
myself.lastRetry = Date.now();
return true;
}
// some more code
}
}
上述代码的问题是this
的值将取决于函数调用的站点。我希望函数能够在不使用的情况下引用自身:
myObject.myFunction
.bind()
.apply()
.call()
问题
是否有可能提供一种独立于其呼叫站点的这种自我意识功能,并且没有外部参考的任何帮助?
答案 0 :(得分:8)
如果要将该状态存储在函数实例上,请为该函数指定一个名称,并在其中使用该名称:
var myObject = {
myFunction: function theFunctionName() {
// ^^^^^^^^^^^^^^^--------------------- name
var firstTime = Boolean(!theFunctionName.lastRetry);
// ^--------------------------- using it
if (firstTime) {
theFunctionName.lastRetry = Date.now();
// ^------------------------------------------------ using it
return true;
}
// some more code
}
};
每当你想要递归地使用函数时,你也会这样做。当您以某种方式为函数命名时(将名称放在function
之后和(
之前),该名称在函数自己的代码中是范围内的。 (如果它是一个函数表达式,它不在包含该函数的代码的范围内,但如果它是一个函数声明,那就是它。你的是一个表达式。)
这是一个命名函数表达式(之前你有一个匿名函数表达式)。您可能听到有关NFE的警告,但各种JavaScript实现与它们之间的问题基本上都是过去的。 (IE8仍然错误地处理它们:this post on my blog中的更多内容。)
你可以考虑通过IIFE将该状态保存在某个私密的地方:
var myObject = (function(){
var lastRetry = null;
return {
myFunction: function() {
var firstTime = Boolean(!lastRetry);
if (firstTime) {
lastRetry = Date.now();
return true;
}
// some more code
}
};
})();
现在,外部匿名函数之外的任何内容都看不到lastRetry
。 (如果你支持顽固的XP用户,你不必担心IE8。:-))
附注:一元!
运算符始终返回一个布尔值,所以你的
var firstTime = Boolean(!theFunctionName.lastRetry);
......完全等同于:
var firstTime = !theFunctionName.lastRetry;
...但是有一个额外的不必要的函数调用。 (不是它会伤害任何东西。)
答案 1 :(得分:0)
当然你可以简单地给你的函数一个内部命名表示,它可以从那里引用它自己。例如......
var obj = {
doThings:function doThingsInternal(arg1, arg2) {
console.log(arg1, arg2);
for (var arg in doThingsInternal.arguments) {
console.log(arg);
}
}
};
obj.doThings('John', 'Doe');
答案 2 :(得分:0)
如果你不太愿意在函数中保持状态存在知识,你可以使用一个简单的闭包。但我猜你不想那样。另一种方法是在第一次调用时更改函数本身。好处,不需要/更少的状态变量,并且不会对后续调用进行昂贵的检查! -
var myObject = {
myFunction: function () {
// Whatever you wanna do on the first call...
// ...
// And then...
this.myFunction = function(){
// Change the definition to whatever it should do
// in the subsequent calls.
}
// return the first call value.
}
};
您可以通过更改您所在州的功能定义,将此模型扩展到任何状态。