2012-10-10
グローバルオブジェクトを環境依存せずにstrict-modeでも取得
どーもこんちわ。JavaScript typeof演算子で存在判定 であげたリンク先に追記してあったグローバル周りの取得、そんなに困るように見えなかった
@Hiraku さんは今もう解決してるかもだけど、strict mode('use strict';
)普及したとき誰か見るかもしれないから置いとく
「ReferenceError対策」のところ
この引用エントリは「undefinedを厳密に見る」のに主眼を置いてるから、こういうコードになってるのに注意
いちおうグローバルオブジェクト(要はwindow)を使えば、==nullでグローバル変数の存在確認も書けます。が、環境依存になってしまう(node.jsとかにはwindowがありません)ので、教科書的にはアウトな表現ですね。。難しいなあ…
if (window.a == null) { //これならReferenceErrorは起きない alert("aは未定義!"); }JavaScript:undefined値の判定: Architect Note
ほとんどの場合はnullとundefined厳密に判定必要ないから、falsyひとくくりでじゅうぶん
if (!window.a) { //... }
で、ここではwindow
になってるグローバルオブジェクトだけど、取るのにあんまり環境依存ないと思う
node.jsはあらかじめglobal
さんがいるけど、あれは意味がちょっと違う気がしないでもない
いわゆる「グローバルオブジェクト」
グローバル / トップレベル + オブジェクト / コンテキスト / スコープって、言葉がよくないと思う。同じこというのに人によって組み合わせ違う
「スコープ」はまだしも「コンテキスト」は語彙が広すぎて話題によってニュアンス違って割と困る。とか言いながら結構ちゃんぽんで使ってる。だめだこりゃ
いきなり完成品
すぐ試したいひとは下のコードを、コンソール・UserScript・node.js・jsファイルとかで実行すると大体挙動わかるとおもう
実際使うときはたぶんこんな感じ。new
省略してる。varなglobal
が気に食わないひとは適当な名前に変えてね。あ、console
IEで引っかかったらalert
とかで
(function () { 'use strict'; var _g = 'g', _t = 't'; (function () { var global = Function('return this')(); _g = global; _t = this; })(); console.log('_g', _g); // => _g window console.log('_t', _t); // => _t undefined })();
'use strict;'
はじめて使ってみたけど、function スコープとグローバルオブジェクトに限れば特に難しくない
'use strict;'
が伝播するのと、this
の挙動が変わるの知っとけば大丈夫そう
'use strict;' の伝播
-
'use strict;'
をfunction内に書くと strict mode になる - strict mode は内側の(or ネストした or 下位階層の)スコープに伝播する
- どのスコープから
'use strict;'
してもいい
大体あってるとおもう
thisの挙動
'use strict;'
前
'use strict;'
後
- new しないで
this
キーワード使ったときundefined
になる
大体あってるとおもう。こればっかし
ここからグローバルオブジェクトの取り方色々
レガシーなタイプ
主にグローバルコード(コンテキスト)でthisするやつ。超フツーのよくみる、というか今までよく見てたタイプ
functionの引数でthis
(function (global) { console.log(global); })(this)
UserScriptでたまに使われてる
即時関数内でreturn this
引数何も使わないで、値を保持しておいたりする
var global = (function () { return this; })();
strict mode だとundefined
が返ってアウト
トップでthis
strict mode でも使えるっちゃ使える
'use strict'; console.log(this);
ただ、トップスコープ以外だと制限かかるからあんまり便利でもない
Functionコンストラクタ
いまんとこ一番汎用性高いっぽいやつで、文字列コンストラクタだからevalの親戚みたいな。strict mode でもこうやって
function () { 'use strict'; var global = Function('return this')(); }
スコープ気にせずどこでも取れる。strictの下位伝播にストップ掛けてる感じ。黒魔術っぽいけど
indirect call to eval
間接的eval呼び出し。これも strict mode 対応でどのスコープでもいける
function () { 'use strict'; var global = (1, eval)('this'); }
こうとか。evalがマジevilでますます黒魔術
カンマ演算子って捉えてる(1, eval)
のところ、どう書くとスマートか?というとどれもスマートじゃない気がする
下のサイトでパターンがすごいあるの見て是非うんざりして欲しい
eval系の挙動盛り合わせサラダ
@kangax さんがまとめたやつ。魔法めちゃくちゃいっぱいあってすごい。特にどこがいいかって言うと、コメント欄にしれっとDavid Flanagan卿(@__DavidFlanagan)がいるのが見どころ
例にあげたindirect call to eval、new Functionも出てるし、他にも色々変態なのあるから好きなの使うといいとおもう
テストページ
見てるブラウザで動くかわかる。試しにIE8で行ったら全部ダメでうけた
上部の「Indirect calls:」が「outer」って出れば黒魔術使えてる
@kangax++!