Javascript 是否有可能在没有外部输入的情况下使功能自我感知
背景 我想要一个跟踪自身状态的函数:Javascript 是否有可能在没有外部输入的情况下使功能自我感知,javascript,function,Javascript,Function,背景 我想要一个跟踪自身状态的函数: var myObject = { myFunction: function () { var myself = this.myFunction; var firstTime = Boolean(!myself.lastRetry); if (firstTime) { myself.lastRetry = Date.now(); return tru
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()
是否可以独立于函数的调用站点,在没有外部引用帮助的情况下,为函数提供这种自我意识?如果要在函数实例上存储该状态,请为函数指定一个名称,并在其中使用该名称:
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
}
};
只要你想递归地使用函数,你就会这样做。当您以这种方式给函数命名时(将名称放在函数
之后和(
)之前),该名称在函数自身代码的范围内。(如果是函数表达式,则不在包含函数的代码的范围内,但如果是函数声明,则在该范围内。您的是表达式。)
这是一个命名函数表达式(之前您有一个匿名函数表达式)。您可能会听到关于NFE的警告,但各种JavaScript实现与NFE相关的问题基本上都是过去的问题。(IE8仍然错误地处理它们,不过:更多信息,请参阅。)
你可以考虑通过IIFE:将该状态保持在私有的状态下。
var myObject = (function(){
var lastRetry = null;
return {
myFunction: function() {
var firstTime = Boolean(!lastRetry);
if (firstTime) {
lastRetry = Date.now();
return true;
}
// some more code
}
};
})();
现在,外部匿名函数之外的任何东西都看不到lastrery
(如果您支持顽固的XP用户,您不必担心IE8.:-)
旁注:一元
代码>运算符始终返回布尔值,因此
var firstTime = Boolean(!theFunctionName.lastRetry);
…完全等同于:
var firstTime = !theFunctionName.lastRetry;
…但是有一个额外的不必要的函数调用。(这并不是说它有什么坏处。)当然可以,只需给函数一个内部命名表示,它就可以从那里引用自己。例如
var obj = {
doThings:function doThingsInternal(arg1, arg2) {
console.log(arg1, arg2);
for (var arg in doThingsInternal.arguments) {
console.log(arg);
}
}
};
obj.doThings('John', 'Doe');
如果您不太热衷于将状态存在性知识保留在函数中,那么可以使用一个简单的闭包。但我想你不想那样。另一种方法是在第一次调用时更改函数本身。好处,不需要/更少的状态变量,并且在后续调用中不需要昂贵的检查-
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.
}
};
通过更改每个州的函数定义,您可以将此模型扩展到任何州。您的意思是像…SkyNet?是的,这是可能的。你只想要一个实例吗?(顺便说一句,你不需要上面代码中的Boolean()。事实上,这种意识可能会帮我节省很多工作时间;)@拉比科:是的,在核灾难中被吹走确实会减轻一个人的工作量。:-)请注意,这两种方法都可以工作,而不需要具有对象方法的功能。