2016-05-12 21 views
4

背景是否有可能使一个函数自我意识,而不需要外部

我希望自己的状态的功能保持跟踪:

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()

问题

它是PO是否可以赋予函数这种独立于其调用位置的自我意识,并且没有外部引用的帮助?

+10

你的意思是像...... SkyNet? –

+2

是的,这是可能的。你只想要一个实例吗? (顺便说一下,在上面的代码中你不需要'Boolean()'包装器。) – nnnnnn

+2

由于这个原因而投票结束是世界的结局。 –

回答

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。 (而且你不必担心IE8,如果你支持固执XP用户:-))。


旁注:一元!操作总是返回一个布尔值,让您的

var firstTime = Boolean(!theFunctionName.lastRetry); 

...是完全等同于:

var firstTime = !theFunctionName.lastRetry; 

...但有一个额外的不必要的函数调用。 (并不是说它伤害了任何东西。)

+0

由于您更新了IIFE – andlrc

+1

,所以不需要我的答案请注意,这两种方法都无需具备作为对象方法的功能。 – nnnnnn

+0

@andlrc:伟大的思想...... –

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'); 
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. 
    } 
}; 

您可以通过改变每个状态的函数定义扩展这个模型任何状态。

相关问题