2016-05-12 22 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. 
    } 
}; 

您可以通過改變每個狀態的函數定義擴展這個模型任何狀態。

相關問題