Hatena::Groupptech

ぷちてく RSSフィード

Archive
 
ProfileProfile

2012-10-10

typeof演算子で存在判定するとき

18:38

どーもこんちわ。id:Syoichi() さんのTumblr見て、必要な使いどころ思いだすために書いてみたけどあんまりなさげだった

一見CoffeeScriptっぽいけど、JavaScriptで値の存在確認にtypeof演算子使うメリットがあるのか っていうモロJavaScript実装の挙動のはなし

ただ、コーヒー飲みたかった人にもトランスレータトランスコーダは元の実装知らないとわけわかめ のいい例だとは思う

みんながTumblrのリンク先読んでる前提で書くけど、ナナメ読みしたから変だったらサーセン

ネタ元

ブログコメント*1

typeofが変数の存在確認に使えるの知らなかった…。Strict Modeでもちゃんと使えるみたい。

自分はStrict Modeを使用してJSLintも利用するから変数の存在確認が必要になった事はなかったと思うけど、これはどういう使い所があるんだろう。User Scriptの場合は、サイト側の変数を触る時とかに使えるかな? 大抵はwindowからチェックすれば問題ないけど。

CoffeeScriptでの存在確認演算子のコンパイル結果が2パターンある話 - Syoichi’s Tumblr

1行目のはif(typeof obj !== 'undefined')とかを指して言ったんだとおもう

泥沼なJavaScriptの真偽判定

根本がわからないひとは、ネタ元にあった id:LiosK() さんの

とか、 さんのこのエントリ読むとほぼわかる

falsyが特に暗黒面すぎて、==な自動型変換の魔窟ほぼ覚えてない、というか覚える気があまりない

nullundefinedの区別欲しい場面ないし、厳密比較演算子===!==しか使わないで過ごしてる

typeofで存在確認するメリット

結論から言うと「これに必須!」とか「この方がいい!」って強くいうまでのメリットはわからない

引っ張っといてアレだけど、気になるから書いてるかんじ。いつも通り実行スピードは気にしない前提

ただし何回か使った具体例があるので、それを出して何となくこうなんじゃないかっていうボヤっとした感じで

typeof obj === 'undefined' 系

これ、今はそんなに意味ないんじゃないか と思ってて、リンク先にあったとおり、未定義でReferenceError(TypeError)にならないっていうだけかなと

if (typeof obj === 'undefined') return;

とか

if (typeof obj !== 'undefined') {
    // do something
}

とかの記述で、objが定義されてなくてもぶっ飛ばないのがメリット。ただ冗長になる

requireとか別のjsファイルと連携する場合とか、都合いいのかも

でもシンプルにしたい

大体こういう場合は単に存在確かめるだけだから

if (!obj) return;

とか

if (obj) {
    // do something
}

こう書けるように、可能な限り前でvar宣言したりhoisting使って暗黙的に引き上げた方が多分読みやすい

サイト側のスクリプト確認

BookmarkletとかUserScript内からサイト側スクリプトを触るのは割とベタで、特にフレームワーク(FW)を借りたり書き換えたりするタイプは多い

例えばTen.js

触ること多いのはTen.jsとかHatenaStar.js。Tenははてな製のFWで、HatenaStar.jsの中とか単独とかで使われてる。グローバルに名前空間でぶら下がってるタイプ。こんな構造

      Window (Global)
   ┬─────────┬
   └ Ten              └ Hatena 
      ├ Array - …        ├ Star - …
      ├ Browser - …      ├ User - … 
      :                    :

はてなのサービスには大体いて、はてなスターが付いてれば外部サイトでも確実にいる

この時点で世間とちょっとズレてるけど・・まぁ普通のひとでいうjQuery

Bookmarkletでtypeof

これは別にたいしたことしてないんだけど、ガード節でif (typeof Ten !== 'object') return;してる

(function () {
    if (typeof Ten !== 'object') return;
    
    if (/^http:\/\/f\.hatena\.(?:ne\.jp|com)\/[\w-]+\/\d{14}/.test(location.href)) {
        var fotoSyntax = Ten.querySelector('#breadcrumbs input');
//...
})();
Foto2Haiku - Hatena::Let

なんで使ってたかよく覚えてないけど、たぶんこういう感じ

  1. javascript:コンテキストだとwindowオブジェクト共有してる
  2. Tenはwindow.Tenにいる
  3. Ten.querySelectorモロモロを使うにはTenの名前空間が汚染されてない保障がいる
  4. Tenが存在しても汚染されてないとは限らない
  5. だからtypeof Ten !== 'object'で、Tenがオブジェクトだっていう担保しよう

「単純な存在確認 + オブジェクト(FW)担保」 って目的だったと思う

  • 名前がサイト側・Bookmarklet(・UserScript)とかで使われやすそう

とかいう場合はいいかもしれない。ネーミング変えられない場合とか。ただ・・

FW担保弱い

上のコードだとこうやられたらもう素通りアウトだから確実性はあんまりない

javascript:void(Ten = {});

なので最近めっきり使ってない。

シンプルにそこにいればいいやって感じで、FWタッチする程度なら

(function () {
    if (!Ten || !Ten.querySelector) return;
//...
})();

使うやつチェックしてこう書いてる傾向にある

FW担保強くするなら

FWが独自で持ってる独特なプロパティ見る方がいいかも。たとえば

if (Ten.NAME === 'Ten') {
//...
}

こういうのだけど、typeof 元も子もないね><

UserScriptでtypeof

こっちもあんまり使うこと無いんだけど、あるにはある

typeof obj === 'undefined' 系
(function () {
//...
    var fancyExpand = function () {
        if (typeof window.Hatena === 'undefined' || typeof window.Hatena.Star === 'undefined') return;
//...
    }; // /fancyExpand()
//...
})();
no title
typeof obj !== 'object' 系
(function () {
//...
    var avatarize = function () {
        if (typeof window.Hatena !== 'object' || typeof window.Hatena.Star !== 'object') return;
//...
    };
//...
})();
no title
・・何でだっけ

Bookmarkletのとこで上げた「単純な存在確認 + オブジェクト(FW)担保」 って要因の他にUserScriptならではの理由あったはずなんだけど、さっぱり思い出せない

両方ともforkしたやつだから、基本「動いてるところはいじらない」メソッドでそのままにしてる ってのもあるけど、windowがらみで何かあったような・・

テスト前に掃除したくなるアレ
  • そういえば最近windowってエンジンでラップするのが普通になって来てるんだっけか

とか、

  • 例に上げた2つのUserScriptって、ちょっと小ワザ使ってるからwindow普通に書いたときと違うかも

とか、全然関係ないこと沢山思い出してきた。長いから各UserScriptのエントリ上げる機会に分けて書くことにする

理由がわかりそうな人向け

晒してるコードの古いリビジョンは typeof 結構使ってたはずなので、エスパーが見たらわかるとおもう

Gistの公式検索バグってて、messageとか古いのキャッシュしたままだし、件数が水増しされて出てくる。ブラウザキャッシュ切ってもダメだった。検索結果画面すごくきれいなのにもったいない。

Googleドメイン指定検索、格好よくは無いけどけどちゃんと仕事した

デザインきれいな方がイケてないの、見かけ倒し感強まって悲しい

*1Tumblr用語として正しいかわからない

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