Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/450.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否有可能在没有外部输入的情况下使功能自我感知_Javascript_Function - Fatal编程技术网

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()。事实上,这种意识可能会帮我节省很多工作时间;)@拉比科:是的,在核灾难中被吹走确实会减轻一个人的工作量。:-)请注意,这两种方法都可以工作,而不需要具有对象方法的功能。