JavaScriptのnewって要るの要らないの、どっち?(シリーズその4)

More than 3 years have passed since last update.

「必要なのはJavaScript言語仕様書とブラウザーコンソールだけ!」

シリーズ、その4。


new を使わない時と使ったときの違い

JavaScriptには「new」という予約語がある。重要な意味を持つ予約語である。いったいどんな働きがあるのだろうか?

例えば実験として、「new」を使わない場合と使う場合を比べてみる。

var x1 = Object()

var x2 = new Object()
x1
x2

と打ち込んだ場合、x1とx2にはどのようなものが与えられるのか、という疑問。

結果:

2015-12-08 18_51_47-Start.png

Objectオブジェクトの場合は「new」があってもなくても結果は同じだった。しかし、これはObjectオブジェクトの場合であり、他のbuilt-inオブジェクトでは同じ場合もあれば異なる場合もある。JavaScript言語仕様がそれを明示的に規定している。

Objectオブジェクトの仕様をよく見ると、Object() の場合と new Object() のそれぞれの働きが定義されていて、ざっくり言うと、同じ振舞になる、っと書いてある(new 有りの方は分岐やケースを含むアルゴリズムだが、基本的には新しいオブジェクト(ECMAScript object)が生成されるとある。)


他のbuilt-inオブジェクトのコンストラクタで「new」の効果を調べてみる

以下のbuilt-inオブジェクトに対してそれぞれ,「new 無し」と「new 有り」の場合を調べてみる。

Function オブジェクト

Function() :「new 有り」と同じ振舞をする(新たに作成されたオブジェクトが返される)。

new Function() : 新たに作成されたオブジェクトが返される。

どちらもオブジェクトが返される。

Array オブジェクト

Array() :「new 有り」と同じ振舞をする(新たに作成されたオブジェクトが返される)。

new Array() : 新たに作成されたオブジェクトが返される。

どちらもオブジェクトが返される。

今のところ、「どちらもオブジェクトが返される」というパターン。

でもStringはちょっと違う。

String オブジェクト

String() : 新しいオブジェクトは作成されない。Stringのが返される。(例:””や”hello”など)

new String() : 新たに作成されたオブジェクトが返される。

new 有りの場合だけオブジェクトが返される。

これは検証の価値あり。コンソールに下のように入力し、結果を調べる。

var s1 = String()

var s2 = new String()
s1
s2

結果:

2015-12-08 19_18_28-Start.png

s1が空の文字列を返すところ、s2はLengthというプロパティを持つ、れっきとしたStringオブジェクトを返していることに注目。

さらに調査を進める。

Boolean オブジェクト

Boolean() : 新しいオブジェクトは作成されない。Booleanのが返される。(パラメーターを指定しない場合はfalse

new Boolean() : 新たに作成されたオブジェクトが返される。

new 有りの場合だけオブジェクトが返される。

BooleanはStringと同じパターンで、new の有る無しで結果が異なる。

検証してみる。

var b1 = Boolean()

var b2 = new Boolean()

結果:

2015-12-08 19_23_53-Start.png

やはり new がある場合のみ、オブジェクトが返ってきている。

さらに先に進もう。

Number オブジェクト

Number() : 新しいオブジェクトは作成されない。Numberのが返される。(パラメーターを指定しない場合は0

new Number() : 新たに作成されたオブジェクトが返される。

new 有りの場合だけオブジェクトが返される。

StringとBoolean組に新たにメンバーが加わった。

検証は以下のようにコンソールに入力:

var n1 = Number()

var n2 = new Number()
n1
n2

結果:

2015-12-08 19_27_11-Start.png

予測どおり、n2はオブジェクトだが、n1は単なる数。

Date オブジェクト

Date() : 新しいオブジェクトは作成されない。NumberのがStringとして返される。これはあたかもtoString()関数が呼び出された場合と同じ結果になる。

new Date() : 新たに作成されたオブジェクトが返される。

new 有りの場合だけオブジェクトが返される。

これは検証結果をよく観察しないと違いが分かりずらいかもしれない。

2015-12-08 19_33_43-Start.png

d1の値は""で囲まれたStringであるが赤色で表示されている。一方、d2の値はオブジェクトで、そのオブジェクトの内容が、仮にtoString()が呼び出された場合の値を表示している。

最後にError オブジェクトを調べてみる。

Error

Error() : 「new 有り」と同じ振舞をする(新たに作成されたオブジェクトが返される)。

new Error() : 新たに作成されたオブジェクトが返される。

どちらもオブジェクトが返される。

ErrorはObjectやFunctionと同じパターンで、new の有無に関わらず、新しいオブジェクトが生成される。

検証結果:

2015-12-08 19_41_51-Start.png

e1もe2もオブジェクトを指している。


結局 new は要るの要らないの?

原則として「オブジェクトを作りたいという気持ち」があるならば new から入力し始める、というルールでOKではないだろうか?その点に関しては一貫しているので。

さて、ここまで built-in オブジェクトを使って、new 有り・無しでオブジェクトを作れるかどうかを試してきた。言語仕様に基づき、オブジェクトが作成される場合とそうでない場合があることが分かった。

だからと言って、オブジェクトを作る方法が new だけとは限らない・・・ JavaScriptの「同じ結果を出すのにいくつもの方法がある」という特徴の一つである。


Object.create()を使ってオブジェクトを作る

JavaScriptでは

Object.create(...)

というfunctionを使ってオブジェクトを作ることが可能。

その5につづく