読者です 読者をやめる 読者になる 読者になる

メモを揉め

お勉強の覚書。

javascriptのオブジェクトリテラルは評価されるまでは、あくまでブロック文でしかない

よくよく考えたら普通のことでした。
評価せずに使われる場面も思いつかないのでわざわざ書くことでもないと思うのですが、何が役に立つか分からないこの世の中。
一応メモ。

そもそも何故気になったか

算術演算子の動作を調べるために色んな物同士を演算子で連結して遊んでいた。
その中でどうも腑に落ちない式がありました、オブジェクトリテラル同士を演算子でつないだものです。(使い道は無いと思いますが…)

 

{0:0}+{0:0}    //エラー

あれ?なんでエラーになるんだろう?
と思って考えましたが理由が分かりませんでした、それでいろいろ試したところ

 

{a:0}+{0:0}    //NaN

{a:0}*{0:0}    //エラー

となって、さらに混乱。

ブロック文とラベル文

オブジェクトリテラルってなんだっけと思い、safariのコンソールに

 

{}

と空オブジェクト(のつもり)を打ち込んでリターンを押すとundefined が返ってくる。
自分としては"object"とかになることを期待していたのでおかしいと思った。 そしてここで、ふと「ブロック文」のことを思い出す。

ブロック文 - JavaScript | MDN

あーそうかこれかー、

javascriptにはブロックスコープは無く、あるのは関数スコープのみです。
ブロック文を単独で使う意味はほとんど(あるいは全く)無く、for文やif文などでしか使わないので忘れていたのです。

改めて式を観察して考えました。

 

{}

これは、ただのブロック文だったんですね。
だからundefinedがコンソールから返ってきます。だから、

 

({})

こうするとちゃんとオブジェクトが返ってきたことを表す▼Objectが表示されました。

ということで前述の、

 

{a:0}+{0:0}    //NaN

{0:0}+{0:0}    //エラー

2つの違いは左の{a:0}{0:0}だけです。
これをブロック文として解釈すると…

 

{
  a:
  0
}

{
  0:
  0
}

はい、そうです。ラベルですね。

ラベル付きステートメント (JavaScript) - MSDN - Microsoft

これがまた使わないんですわ…、すっかり忘れてました。

 

{a:0}    //0

{0:0}    //エラー

前者はaというラベルの付いた0だけの文、
後者は0がラベル名に使えないのでエラーになったんですね。

そしてもう一つ、

 

{a:0}+{0:0}    //NaN

{a:0}*{0:0}    //エラー

2つの違いは+*です。
{a:0}をブロック文として解釈すると、

 

{
  a:
  0
}
+{0:0}

{
  a:
  0
}
*{0:0}

つまり+{0:0}は、単項演算子+の付いたオブジェクトリテラルと解釈でき、
*{0:0}*二項演算子なので、左側に被演算子が無いからエラーになったんですね。

オブジェクトリテラルは評価されるまではブロック文

ここまでのことを踏まえて考えると、オブジェクトリテラルは式として評価されるまではブロック文ということみたいです。

 

{
  a : {
    b : {
      c : "statement"
    }
  }
}

上のコードをコンソールで実行すると、"statement"と返ってきます、つまりブロック文とラベル文として解釈されています。

以下はすべてオブジェクトリテラルとして解釈されます。

()で囲む

 

({
  a : {
    b : {
      c : "statement"
    }
  }
})           //▼Object

+を付ける

 

+{
  a : {
    b : {
      c : "statement"
    }
  }
}            //NaN

!を付ける

 

!{
  a : {
    b : {
      c : "statement"
    }
  }
}            //false

~を付ける

 

~{
  a : {
    b : {
      c : "statement"
    }
  }
}            //-1

typeof演算子

 

typeof {
  a : {
    b : {
      c : "statement"
    }
  }
}            //"object"

in演算子

 

"a" in {
  a : {
    b : {
      c : "statement"
    }
  }
}            //true

delete演算子

 

delete {
  a : {
    b : {
      c : "statement"
    }
  }
}            //true

void演算子

 

void {
  a : {
    b : {
      c : "statement"
    }
  }
}            //undefined

まとめ

冷静に考えれば「文」として成立している以上、「文」として解釈されないとむしろ問題ですね、ほんとうにありがとうございました。