MENU

JavaScript構文

【JavaScript】 今更だけど非推奨なwith構文を理解してみる

更新日:2021/01/11

 

JavaScriptにはwith構文というものがあります。
あまり聞きなれない構文ですが、使用することでコードを簡潔に記述できます。
ただし非推奨です。

 

オブジェクトのプロパティをスコープ解決に組み込む

 

with構文を使用すると、オブジェクトのプロパティをスコープ解決に組み込むことができます。

 

次のコードはエラーになります。

 


const obj = {
    prop1:"a",
};

console.log( prop1 ); // ReferenceError: prop1 is not defined

 

objが所持するprop1プロパティを参照するには、ob.prop1と記述する必要があるからです。

 

しかし次のようにwith構文を使用すると、obj内のプロパティも探すようになります。

 


with(obj){
    console.log( prop1 ); // "a"
}

 

ローカル変数も通常のスコープ解決方法で処理されますが、優先度はwithで指定したオブジェクトの方が高いです。

 


const obj = {
    prop1:"a",
};

let prop1 = "b";
let prop2 = "c";

with(obj){
    console.log( prop2 ); // "c" 
    console.log( prop1 ); // "a" ← ローカルよりもobjが優先された
}

 

なおwith構文はstrictモードでは使用できません

with構文は非推奨

 

with構文は誰が言っているのかはわかりませんが、非推奨です。
言語仕様上では特に言及していませんが、with構文がstrictモードでは使用できないことからも、排除したい意思を感じます。

 

非推奨の理由は、バグが発生しやすいことが挙げられます。

 

例えば次のようなコードがあるとします。

 


const obj = {
    prop1:"a",
    ・・・多くのプロパティ
    prop2:"b",
    ・・・多くのプロパティ
};

・・・数百行のコード

let prop2 = "c";

with(obj){
    console.log( prop2 );
}

 

let prop2 = "c";で定義した変数を使用するつもりが、obj.prop2を使用しているというケースです。
場合によっては、気が付くのに非常に時間がかかる可能性があります。

 

また仕様変更で後からobjにprop2を追加することがあるかもしれません。
その際with構文を使用しているなら、同名の変数が使用されていないか全て洗い出す必要があります。

 

そうしないとオブジェクトにデータを追加しただけで、今まで動いていたものが不具合をおこす可能性があるのです。
とても怖いですね。

Symbol.unscopables

 

[Symbol.unscopables]プロパティを使用すると、オブジェクトのプロパティをwith構文での検索対象から除外できます。

 


const obj = {
    prop1:"a",
    prop2:"b",
    [Symbol.unscopables]:{
        prop1:true, // 除外する
        prop2:false // 除外しない
    }
};
let prop1 = "c";
let prop2 = "d";

with(obj){
    console.log( prop1 ); // "c" ←ローカル変数
    console.log( prop2 ); // "b" ←obj.prop2
}

 

これを使用すれば細かい制御ができるのですが、「prop1はどこを見る?」「prop2はどこを見る?」と一つ一つ確認していく必要があるのはかわりありません。
とても面倒です。

 

obj.prop1と素直に記述したほうがわかりやすいですね。

長いオブジェクト名を記述するのが面倒なら

 

with構文の使用目的の一つに、長いオブジェクト名を記述するのが面倒ということがあります。

 

例えば次のようにネストされたオブジェクトを一つ一つ辿って記述していくケースなどです。

 


const obj = {
    obj2:{
        obj3:{
            prop:"a"
        }
    }
}
console.log( obj.obj2.obj3.prop ); // "a"

 

with構文を使用すると簡潔に書くことができます。

 


with( obj.obj2.obj3 ){
    console.log( prop ); // "a"
}

 

しかし上述の理由で非推奨ですし、そもそもstrictモードでは使用できません。

 

おススメは、次のようにオブジェクトを変数に代入することです。

 


const obj3 = obj.obj2.obj3;
console.log( obj3.prop ); // "a"

記事の内容について

 

こんにちはけーちゃんです。
説明するのって難しいですね。


「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

そんなときは、ご意見もらえたら嬉しいです。

ご意見はこちら。
https://affi-sapo-sv.com/info.php

【お願い】

お願い

■このページのURL


■このページのタイトル


■リンクタグ