0

我使用一個名爲下面的函數isExpression,以確定一些JavaScript代碼是一個表達式:確定是否JavaScript代碼是一種表達

function isExpression(code) { 
    try { 
     new Function("return " + code); 
     return true; 
    } catch (e) { 
     return false; 
    } 
} 

它可以正確處理所有的測試用例,除了一個 - 它不正確把一個FunctionDeclaration作爲FunctionExpression並返回true代替false。有沒有辦法解決這個問題,而不必編寫解析器?

+0

怎麼樣'新功能(代碼+「+ 0」);'?等一下; 'new Function(code.replace(/ \ n/g,'')+「+ 0」);'...不,這也行不通。可能你必須寫一個解析器:-) – Pointy 2012-08-12 14:18:59

+3

我不認爲你可以。函數聲明是表達式上下文中的有效表達式。因此,如果您只是在表達式上下文中評估代碼,則無法區分差異。 – 2012-08-12 14:21:51

+0

@Pointy - 它沒有任何區別。它仍然會將__'FunctionDeclaration'__視爲__'FunctionExpression'__。 – 2012-08-12 14:22:54

回答

0

由於@FelixKling指出確定一個函數是否是一個聲明而不是一個表達式的唯一方法是檢查該函數的上下文。但是,在REPL(其中isExpression函數的意圖)中沒有上下文。因此事情變得更簡單。

鍵入REPL的code只能是一個函數聲明,如果它以關鍵字function(在修剪開頭的空白之後)開頭的話。因此可以通過正則表達式/^\s*function\s/進行測試。

@FelixKling指出這樣一個函數可能仍然是一個表達式,而不是一個聲明,這取決於函數的上下文(即函數是一個表達式,如果它是一個non-source element)。但傳遞給此函數的code保證是源元素。

如果這樣的功能構建體使用條件操作符(例如function f() {} ? x : y)或使用逗號操作者用來作爲表達(例如function f() {}, x)然後isExpression仍然會返回false。然而,這樣的代碼會引起SyntaxError。因此的isExpression以下實現將正確地測試一些代碼是否適用於所有情況的表達式:

var isExpression = function (functionDeclaration) { 
    return function (code) { 
     if (functionDeclaration.test(code)) return false; 

     try { 
      Function("return " + code); 
      return true; 
     } catch (error) { 
      return false; 
     } 
    }; 
}(new RegExp(/^\s*function\s/)); 
-1

通過檢查您的構造函數返回值的類型,我們可以確定原始表達式是一個函數。

function isExpression(code) { 
    try { 
     return typeof (new Function("return " + code))() !== 'function'; 
    } catch (e) { 
     return false; 
    } 
} 

警告:該字符串中的調用將被調用。這可能會使這不太有用。

+0

但是目標是確定它是一個函數表達式還是一個函數聲明。 – Quentin 2012-08-12 14:40:06

+0

如果'code'真的是一個函數表達式(例如'(function(){})''),那麼這將是錯誤的。 – 2012-08-12 14:41:47

+1

請參閱http://jsfiddle.net/7HVkK/ - 您會得到相同的結果。正如對問題的評論指出的那樣,函數表達式和函數聲明之間的區別在於代碼出現的上下文。在它前面粘貼'return'(就像你的代碼一樣)將它變成一個函數表達式。 – Quentin 2012-08-12 18:03:50

相關問題