クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【JS】オブジェクトのプロパティをCSSのように省略した指定ができるのか検証した

ネイティブJSのやってみたシリーズ。前回まではアロー関数について掘り下げました。今回は基本に立ち返り、オブジェクトのプロパティの指定の仕方を掘り下げます。CSSみたいに途中を省略した書き方はできるのか?普段なんとなく使ってるけどフワッとしていた部分を明確にしました。それではいきましょう!

【目次】

前回記事
※参考:【JS】アロー関数のthisの挙動(プロトタイプとクラスの違い) - クモのようにコツコツと

※参考:ネイティブJSでいろいろやってみたシリーズ
qiita.com

CSSは省略した指定ができる

例えがこんな階層のHTMLがあるとする。

<section>
    <h1>タイトル</h1>
    <p>本文です。本文です。本文ですたら本文です。本文です。本文です。本文ですたら本文です。本文です。本文です。本文ですたら本文です。本文です。<b>ここ重要!テストに出るぞ。</b>本文です。本文ですたら本文です。本文です。本文です。本文ですたら本文です。本文です。本文です。本文ですたら本文です。本文です。本文です。本文ですたら本文です。</p>
</section>

sectionタグの中にpタグがあり、pタグの中にbタグがある。

CSSの指定はわりと自由。

/* 全部指定 */
section p b {
    color: red;
    font-weight: bold;
}

/* 省略指定 */
section b {
    color: red;
    font-weight: bold;
}

/* 単独指定 */
b {
    color: red;
    font-weight: bold;
}

上記の3つの書き方のどれでもCSSのスタイルはあたる。(ただ、詳細度によって同じスタイルが重複した時の優先順位は変わる)

※参考:【CSSの基本】書ける前に読む!HTML、CSS、JSの書式-3 - クモのようにコツコツと

同じような指定の仕方がJSのオブジェクトでも可能なのか検証したい。

JSオブジェクトのプロパティ指定テストを作った

作ってみたものがこちら。

See the Pen JS Object test_1 by イイダリョウ (@i_ryo) on CodePen.

ボタンを押すとアラートが立ち上げるが、それぞれの表示されるテキストが異なる。

HTMLコード

<div class="btns">
    <p>ネストしたオブジェクトを省略して指定できるかテスト</p>
    <button class="obj">オブジェクト</button>
    <button class="zenbu">全部指定</button>
    <button class="shoryaku">省略指定</button>
    <button class="tochu">途中指定</button>
    <button class="chukan">中間指定</button>
</div>

.btnsの中にボタンがいくつかあり.obj. zenbu. shoryaku. tochu.chukanと言うクラス名をつけている。

JSコード

//オブジェクト設定
const testObj = {
    aaa: {
        iii: {
         uuu: {
            eee: "ooo" 
            }    
        }
    }
}

//プロパティ指定
const objZenbu = testObj.aaa.iii.uuu.eee;
const objShoryaku = testObj.eee;
const objTochu = testObj.aaa.iii;
const objChukan = testObj.iii;

//DOM取得
const obj = document.querySelector('.obj');
const zenbu = document.querySelector('.zenbu');
const shoryaku = document.querySelector('.shoryaku');
const tochu = document.querySelector('.tochu');
const chukan = document.querySelector('.chukan');

//クリックイベント
obj.addEventListener( 'click', function () {
    alert( testObj );
 }, false );

zenbu.addEventListener( 'click', function () {
    alert( objZenbu );
 }, false );

shoryaku.addEventListener( 'click', function () {
    alert( objShoryaku );
 }, false );

tochu.addEventListener( 'click', function () {
    alert( objTochu );
 }, false );

chukan.addEventListener( 'click', function () {
    alert( objChukan );
 }, false );
  • 変数testObjでオブジェクトを作っている。入れ子構造になっている
  • 変数objZenbu、変数objShoryaku、変数objTochu、変数objChukanでオブジェクトを指定している
  • 変数obj、変数zenbu、変数shoryaku、変数tochu、変数chukanでHTML上のDOMを取得
  • objzenbushoryakutochuchukanのクリックイベントを設定

以下でコードの詳細を見ていく。

入れ子階層のオブジェクトを作る

//オブジェクト設定
const testObj = {
    aaa: {
        iii: {
         uuu: {
            eee: "ooo" 
            }    
        }
    }
}
  • 変数testObjの値は連想配列
  • testObjの連想配列にはaaaキーがあり、この値も連想配列
  • aaaの連想配列にはiiiキーがあり、この値も連想配列
  • iiiの連想配列にはuuuキーがあり、この値も連想配列
  • uuuの連想配列にはeeeキーがあり、この値はoooと言う文字列

testObjオブジェクト > aaaプロパティ > iiiプロパティ > uuuプロパティ > eeeプロパティ > 値ooo

と言う構造になっている。

プロパティの指定方法(全部、省略、途中、中間)

testObjオブジェクトのプロパティをいろんな指定の仕方で設定してみる。

//プロパティ指定
const objZenbu = testObj.aaa.iii.uuu.eee;
const objShoryaku = testObj.eee;
const objTochu = testObj.aaa.iii;
const objChukan = testObj.iii;
  • 変数objZenbuではeeeプロパティを指定するために全てのプロパティを書く(testObj.aaa.iii.uuu.eee
  • 変数objShoryakuでは途中のプロパティを省略して最後のeeeプロパティを指定(testObj.eee
  • 変数objTochuでは途中のiiiプロパティまでを書く(testObj.aaa.iii
  • 変数objChukanでは途中をすっ飛ばして中間にあるiiiのみを書く(testObj.iii

前半2つは一番最後のeeeプロパティを指定。objZenbuは全部書いてobjShoryakuは途中を省略している。
後半2つは途中のiiiプロパティを指定。objTochuは途中まで全部書いてobjChukanは途中を省略している。

DOMを取得

次にHTMLのDOMを取得する。

//DOM取得
const obj = document.querySelector('.obj');
const zenbu = document.querySelector('.zenbu');
const shoryaku = document.querySelector('.shoryaku');
const tochu = document.querySelector('.tochu');
const chukan = document.querySelector('.chukan');
  • 変数obj.objを取得
  • 変数zenbu. zenbuを取得
  • 変数shoryaku. shoryakuを取得
  • 変数tochu. tochuを取得
  • 変数chukan. chukanを取得

これらのclass名はHTMLのbuttonタグに付けたもの。

クリックイベントを設定(挙動の検証)

最後にクリックイベントを指定している。一つずつ挙動を見ていこう。

オブジェクト自体を指定

まず最初に大元のオブジェクト自体を指定してみる。

obj.addEventListener( 'click', function () {
    alert( testObj );
 }, false );
  • objをクリックするとアラートでtestObjを表示する

testObjはオブジェクト自体だ。どんな結果が出るか?

→結果:「[object Object]」と言うアラートが出る。

このobject Objectと言う結果は「objの中身はオブジェクトですよー」と言う情報を意味している。

オブジェクトの中身(プロパティなど)の情報までは結果に含まれない。

※参考:JavaScript オブジェクトの基本 - ウェブ開発を学ぶ | MDN

オブジェクトの中身の情報を表示したい場合はJSON.stringify()で文字列化する方法がある。

obj.addEventListener( 'click', function () {
    alert( JSON.stringify(testObj) );
 }, false );

このようにJSON.stringify()の引数にtestObjを入れたところ中身が表示された!

→結果:「`{"aaa":{"iii":{"uuu":{"eee":"ooo"}}}}`」と言うアラートが出る。

また、コンソールに表示する場合はconsole.dir()にしてもいいようだ。

※参考:console.logでJSON形式の値が[object Object]になる時 - Qiita

プロパティを全部指定

zenbu.addEventListener( 'click', function () {
    alert( objZenbu );
 }, false );
  • zenbuをクリックするとアラートでobjZenbuを表示する

objZenbuの中身はtestObj.aaa.iii.uuu.eeeで、eeeに至るまでの全てのプロパティを書いている。

→結果:「ooo」と言うアラートが出る。

これは期待通りの結果!まあ全部書いているから当然こうなる。

これを省略した書き方ができるのかを検証したい。

プロパティを省略指定

shoryaku.addEventListener( 'click', function () {
    alert( objShoryaku );
 }, false );
  • shoryakuをクリックするとアラートでobjShoryakuを表示する

objShoryakuの中身はtestObj.eeeで、aaaプロパティ、iiiプロパティ、uuuプロパティを省略している。

→結果:「undefined」と言うアラートが出る。

「undefined」は「定義されてないよ!」と言う意味。

※参考:nullとundefined | JavaScript中級編 - ウェブプログラミングポータル

定義自体はしているんだが、階層的にはtestObjオブジェクトの直下にeeeプロパティを定義しているわけではないため「eeeなんて見つからないよ!」と言う結果になったんだろうな。

やはりJSのオブジェクトのプロパティ指定は厳密っぽいことがわかる。

プロパティを途中まで指定

次、プロパティを途中まで指定してみた。

tochu.addEventListener( 'click', function () {
    alert( objTochu );
 }, false );
  • tochuをクリックするとアラートでobjTochuを表示する

objTochuの中身はtestObj.aaa.iiiと途中の改装までになっている。

→結果:「[object Object]」と言うアラートが出る。

これは最初のtestObjと同じ結果。iiiプロパティの値を見に行ったらuuu自体も連想配列(オブジェクト)なわけなので「オブジェクトがあるよー」と言う事になる。

ちょっとややこしいがJSは値に関数でも変数でも配列でも連想配列でもなんでも入れられるからこうなる。

プロパティの中間を指定

chukan.addEventListener( 'click', function () {
    alert( objChukan );
 }, false );
  • chukanをクリックするとアラートでobjChukanを表示する

objChukanの中身はtestObj.iiiで、iiiプロパティを指定するにあたり途中のaaa`プロパテいを省略している。

→結果:「undefined」と言うアラートが出る。

これはobjShoryakuと同じ結果。testObjの直下のプロパティを見に行って「iiiなんてプロパティは見つからないよー」と言う結果を返している。

最後に

See the Pen JS Object test_1 by イイダリョウ (@i_ryo) on CodePen.

と言うことでプロパティ指定の検証結果はこうなりました。

項目 指定方法 結果
オブジェクト自体を指定 testObj [object Object]
プロパティを全部指定 testObj.aaa.iii.uuu.eee ooo
プロパティを省略指定 testObj.eee undefined
プロパティを途中まで指定 testObj.aaa.iii [object Object]
プロパティの中間を指定 testObj.iii undefined

わかったこと

  • オブジェクトを指定するとobject Objectになる
  • プロパティを指定すると直下の値のみを見る(入れ子階層の場合、さらに下の階層は見てくれない)
  • プロパティの値が文字列の場合は文字列が返ってくる
  • プロパティの値が連想配列(オブジェクト)の場合もobject Objectになる
  • プロパティの上の階層を省略して書くとundefinedになる

JSのプロパティは直下の値しか見に行ってくれないので、CSSのように省略した書き方はできないことがわかりました。オブジェクトの階層自体もあまり深くしない方が指定しやすそうですね。それではまた!


※参考:ネイティブJSでいろいろやってみたシリーズ
qiita.com