LoginSignup
57
57

More than 5 years have passed since last update.

function(){}();はなぜダメなのか、少し掘り下げてみる。

Last updated at Posted at 2015-08-28

グローバル汚染を防ぐために

(function(){
   // code ... 
})();

で囲むけど、これのバリエーションっていろいろある。

バリエーション
// + を使う
+function(){
  // code ...
}();

// - を使う
-function(){
  // code ...
}();

// ! を使う
!function(){
  // code ...
}();

// void を使う

void function()
{
  // code ...
}();

ただこれはだめ。

ダメ
function(){
  // code ...
}();

// nodeだと「SyntaxError: Unexpected token (」となる

これはなぜダメなのかというと、このfunctionは「文」として、例とバリエーションは「式」としてみなされるからだそうだ。このあたり、仕様書を見て少し掘り下げてみることにする。

ECMA2015」の「14.1 Function Definitions」を見ると、


14.1 Function Definitions

Syntax

FunctionDeclaration[Yield, Default] :
  function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
  [+Default] function ( FormalParameters ) { FunctionBody }
FunctionExpression :
  function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
.
.
.

functionは「FunctionDeclaration(function宣言)」と「FunctionExpression(function式)」の2種類ある。あ、「文」と「式」じゃなくて「宣言」と「式」なのか。で、「function式」として解釈されると例やバリエーションのように使えるのである。でもダメな例は「function式」に適合している。なぜだめなのか。それは「Expression Statement(式文)」に書いてある。


an ExpressionStatement cannot start with the function or class keywords because that would make it ambiguous with a FunctionDeclaration, a GeneratorDeclaration, or a ClassDeclaration.

「式」としてみなされるためにはfunctionを文頭におけないルールになっているのである。なぜこうなっているのかというと「function宣言」と紛らわしいから。文頭にfunctionを置くと「function宣言」とみなされる。

しかしなぜ「function宣言」だとダメで、「function式」で解釈されれば良いのかという疑問は残る。

これはJSの言語仕様上「FunctionDeclaration(function宣言)」と「FunctionExpression(function式)」の実行時評価に違いがあるからのようだ。(「のようだ」と書いたのは仕様書の解釈に少し自信がないため)

14.1.20 Runtime Semantics: Evaluationの項を読むと、「function宣言」の戻り値は「empty」である。


FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
 1. Return NormalCompletion(empty).
NOTE 1 An alternative semantics is provided in B.3.3.

FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
 1. Return NormalCompletion(empty).

そして「function式の戻り値」は「closure」となっている。「closure」はFunctionオブジェクトである。

FunctionExpression : function ( FormalParameters ) { FunctionBody }
 1.If the function code for FunctionExpression is strict mode code, let strict be true.otherwise let strict be false.
 2.Let scope be the LexicalEnvironment of the running execution context.
 3.Let closure be FunctionCreate(Normal, FormalParameters, FunctionBody, scope, strict).
 4. Perform MakeConstructor(closure).
 5. Return closure.
 

つまり「function宣言」では「empty(空)」が返るので()をつけるとNGであり、function式の戻り値はFunctionオブジェクトなので()を付けてもOKなのである。

まとめると、

  1. ECMA Script 2015 の言語仕様により、文頭がfunctionで始まる文は、「function宣言」になり、実行時評価後の戻り値が「empty」となるため、()を付加すると文法エラーとなる。
  2. 「式(式文)」の途中に「function」が始まる場合は「function式」となる。「function式」の評価後の戻り値は「Functionオブジェクト」のインスタンスとなる。そのため()を付与して即時に実行することができる。

ということかな?

57
57
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
57