4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

項目10 withは避けよう

Last updated at Posted at 2013-03-24

おはようございますmm今日もやってるワンこです。

最近べジータ様のお料理教室にはまってて中毒症状が起きています。あぁー共感するな~っと思ってさすが王子様>ω<)

本題のEffectiveJavascriptについてですが、あいにく私語学力も技術力も足りず、簡単なものを軽くやると言い訳します。ごめんなさい>ω<)

withのやること

doNotNameYourJSFileLongerThanThisOne.js
function secretPassword(password){
    var thePowerfulAndAwesomePrinceInside = new Bejita();
    with(theAwesomeAndPowerfulPrinceInside){
        doCooking('Okonomiyaki');
        doSinging('I wont tell you my password~');
        alert(password); // Ooops, Bejita's password leaks!!
    }
}

ちなみに上のやつはOoops以前にTypoです>ω<)でうちの王子様のタイトル多いので、withブロックの中では変数やメソッドを使う際自動的にwithに渡したオブジェクトを参照して、いろいろと長いものを入力する手間を省けてくれる。

やってることは ほぼ 下のと同じです

doNotNameYourJSFileLongerThanThisOne.js
function secretPassword(password){
    var thePowerfulAndAwesomePrinceInside = new Bejita();
    thePowerfulAndAwesomePrinceInside.doCooking('Okonomiyaki');
    thePowerfulAndAwesomePrinceInside.doSinging('I wont tell you my password~');
    alert(password); // Feel free to leak your own password
}

したのと比べてwithを使ったのがだいぶ綺麗ですが、バグってしまったらおしまいですね。

なぜwithを使ってはいけないですか?

小難しいことばよくわかりませんが、たぶんこんな感じでしょうか?

withを使うとローカルスコープが汚染される

普通はグローバルスコープへの汚染をしないようにグローバル変数の宣言を控えてますが、使い捨てのローカルスコープも同じってことですね。

withを一度使うと、オブジェクトが一時的にスコープチェーンの先頭にくる。例えてみればオブジェクトのメソッドと変数とプロトタイプの中身などオブジェクトから参照できるものすべてがいまのスコープに入ってくる。普通その内容量は遥かに必要を上回ってますし、一番厄介なのは、普通に参照したいほかのスコープチェーン上の変数とか(password)はオブジェクトのものに上書きされるかもしれません。ローカルにあったから遡ることはしなくなるからです。

危険性というと:

  • オブジェクトに運悪く同名変数関数があると外の本当に参照したいものを参照できなくなる

  • いま安全なオブジェクトでもいつ差分が入って落ちるかもしれません

  • まだ思いついていない

オブジェクトを使う前にいちいち中身をチェックする人はそう多くないと思って、こういう今動いていてもいつ落ちるかわからず、オブジェクトと普通のスコープチェーンのどれを参照しているかわからない状態は汚いといわれても仕方がないですね。

ちなみにwithを使うとstrict modeだと怒られそうです。ES5ではwithより、短い名前の変数にアサインして使うようにと。

doNotNameYourJSFileLongerThanThisOne.js
function secretPassword(password){
    var thePowerfulAndAwesomePrinceInside = new Bejita();
    var t = thePowerfulAndAwesomePrinceInside;
    t.doCooking('Okonomiyaki');
    t.doSinging('I wont tell you my password~');
    alert(password); // Feel free to leak your own password
}

省けた手間よりリスクが大きいってことです。Perlのデフォルトimportもそうですしね。めんどくさいかもしれませんが、システムが大きくなるほど、コードをうるさく書かないといけなくなるものですよ´・ω・`)

Mozillaのwith構文解釈です:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/with?redirectlocale=en-US&redirectslug=Core_JavaScript_1.5_Reference%2FStatements%2Fwith

withは遅いですか?

多少遅くなるかもしれませんが、使わない要因のメインには入れそうもない

サイ本とEffectiveJavascriptによると、遅くて当然だそうです。それもそうです。スコープチェーンの先頭に置くこと自体は重くないが(Mozillaによる)、ローカル変数を訪問するたびにオブジェクトのプロトタイプチェーンをサーチしてみろ!ってことです。

が実際にwithの効率は実装によりますし、SafariやOperaとかだとwith(Math)程度ならほぼスピードは同じの報告もどっかのブログあるらしく、一般的な使用だとそう遅くはないかも。

まぁあくまで一般的な使用です。怪しい使い方でバンバン使うとさすがに遅くなるでしょう。。。

withのほかの副作用

サイ本によると、withの中で変数や関数を宣言したら面白いことになると

きたきたーーーー試してきました!!!`・ω・´)9。

doNotNameYourJSFileLongerThanThisOne.js
function Saiyan( name ){
    this.name   = name;
    this.cutNinjin = function(){
        alert('Cut Ninjin!!!');
    };
    return this;
}

var vegeta = new Saiyan('Vegeta');

with( vegeta ){
    var password = 'sukiyaki';

    alert( name );         // Vegeta
    alert( password );     // sukiyaki

    var name = 'Goku';
    function cutNinjin(){
        alert('Bakibaki Ninjin!!!');
    }
    function cutShoga(){
        alert('Bakibaki Shoga!!!');
    }

    alert( name );         // Goku
    cutNinjin();           // Cut Ninjin!!!
    cutShoga();            // Bakibaki Shoga!!!
}

alert( vegeta.name );      // Goku
alert( vegeta.password );  // undefined
vegeta.cutNinjin();        // Cut Ninjin!!!
//vegeta.cutShoga();       // Error

まとめるとこんな感じです:

  • オブジェクトにあった変数名はvarでローカル宣言しようとしてもオブジェクト変数を上書きしちゃう

  • オブジェクトにない変数名は普通に使える

  • オブジェクトにあった関数名はfunctionで宣言しても使えない、オブジェクトの関数を呼び出すことになっちゃう

  • 上書きにはならない

残念ながら今のところ天下のIEでしか試してないから信憑性が薄いといえる。。。もうちょっとがんばってみる。。。

なぜwithに支持者がいっぱいいるのか?

Googleしてみてください、みんなwithを使いたがってます>ω<)

というのも読みにくいコードを書くの誇りだと思っているプログラマーの悲しい性分。使いにくくなるほど使いたくなるものです。ここでプログラミングと開発作業の違いが出てきましたね。

  • プログラミングは遊び~

  • 開発は仕事だからかな

うちはプログラマーちゃうし、気をつけてやっておこう~
それではご縁があればまた今度~

4
4
0

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
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?