Hatena::Groupptech

ぷちてく RSSフィード

Archive
 
ProfileProfile

2012-10-10

グローバルオブジェクトを環境依存せずにstrict-modeでも取得

18:38

どーもこんちわ。JavaScript typeof演算子で存在判定 であげたリンク先に追記してあったグローバル周りの取得、そんなに困るように見えなかった

@ さんは今もう解決してるかもだけど、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.jsjsファイルとかで実行すると大体挙動わかるとおもう

実際使うときはたぶんこんな感じ。new省略してる。varなglobalが気に食わないひとは適当な名前に変えてね。あ、consoleIEで引っかかったら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;'

大体あってるとおもう。こればっかし


ここからグローバルオブジェクトの取り方色々

レガシーなタイプ

主にグローバルコード(コンテキスト)でthisするやつ。超フツーのよくみる、というか今までよく見てたタイプ

functionの引数でthis

関数の実引数でthisして仮引数global取る

(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系の挙動盛り合わせサラダ

@ さんがまとめたやつ。魔法めちゃくちゃいっぱいあってすごい。特にどこがいいかって言うと、コメント欄にしれっとDavid Flanagan卿(@)がいるのが見どころ

例にあげたindirect call to evalnew Functionも出てるし、他にも色々変態なのあるから好きなの使うといいとおもう

テストページ

見てるブラウザで動くかわかる。試しにIE8で行ったら全部ダメでうけた

上部の「Indirect calls:」が「outer」って出れば黒魔術使えてる

@kangax++!

トラックバック - http://ptech.g.hatena.ne.jp/noromanba/20121010

Copylight (c) noromanba 2012-2017