かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

javascript 即時関数のトラップ

(function() { })();

こんなのを即時関数って呼びます。よく書くと思います。

で、gruntなどでライブラリなどを結合して、min化したりするのですが
この即時関数の前に;が無いと死んでしまうトラップがあったりするので注意が必要です。特に自分で書いていないライブラリと結合した時とか。

いろんな即時関数の書き方

// #1.
/* たぶん一番有名? */
(function() {
  // 処理
})();

// #2.
(function() {
 // 処理 
}());

// #3.
+function() {
 // 処理
}();

// #4.
-function() {
  // 処理
}();

// #5.
/* Twitter Bootstrapとかで使われてる */
!function() {
  // 処理
}();

// #6.
void function() {
  // 処理
}();

// #7.
typeof function() {
  // 処理
}();

即時関数の前に;が無い時の挙動

#1.
var a = 'Sakura'
(function(b) {
  console.log(b);
})(a);

出力結果
Error: Uncaught TypeError: string is not a function

#2.
var a = 'Sakura'
(function(b) {
  console.log(b);
}(a));

出力結果
undefined
Error: Uncaught TypeError: string is not a function

#3.
var a = 'Sakura'
+function(b) {
  console.log(b);
}(a);

出力結果
undefined

#4.
var a = 'Sakura'
-function(b) {
  console.log(b);
}(a);

出力結果
undefined

#5.
var a = 'Sakura'
!function(b) {
  console.log(b);
}(a);

出力結果
Sakura

#6.
var a = 'Sakura'
void function(b) {
  console.log(b);
}(a);

出力結果
Sakura

#7.
var a = 'Sakura'
typeof functionb() {
  console.log(b);
}(a);

出力結果
Sakura


まとめ

  • #1, #2 の方法ではjavascriptのエラーが起こってしまいます。
  • #3, #4 の方法はエラーは発生しませんが、即時関数の引数で値を渡せません。
  • #5, #6, #7 の方法は期待した結果になりました。

レギュレーションなどで 即時関数は #1 の書き方で!とか
決められているプロジェクトの場合、とりあえず即時関数の先頭に;を置くことで
jsのエラーを回避することもできます。

var a = 'Sakura'
;(function(b) {
  console.log(b);
})(a);

出力結果
Sakura

僕としては、全て自分で作ったjsファイルならJSHintなどで;の書き忘れをチェックしてなくしちゃえば済む話なので#1が書き慣れているのですが、他のライブラリファイルとかと結合したりするのであれば、#5 の

!function() {
  // 処理
}();

がタイプ数も少ないし、TwitterBootstrapでも使われているし解りやすいのではないかなぁと思いました。


[参考]
https://tomoyamkung.net/2014/03/08/sublimetext3-sublimelinter-jslint/

開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質

開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質