「必要なのはJavaScript言語仕様書とブラウザーコンソールだけ!」
シリーズ、その4。
#new を使わない時と使ったときの違い
JavaScriptには「new」という予約語がある。重要な意味を持つ予約語である。いったいどんな働きがあるのだろうか?
例えば実験として、「new」を使わない場合と使う場合を比べてみる。
var x1 = Object()
var x2 = new Object()
x1
x2
と打ち込んだ場合、x1とx2にはどのようなものが与えられるのか、という疑問。
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
s1が空の文字列を返すところ、s2はLengthというプロパティを持つ、れっきとしたStringオブジェクトを返していることに注目。
さらに調査を進める。
Boolean オブジェクト
Boolean() : 新しいオブジェクトは作成されない。Booleanの値が返される。(パラメーターを指定しない場合はfalse
)
new Boolean() : 新たに作成されたオブジェクトが返される。
new 有りの場合だけオブジェクトが返される。
BooleanはStringと同じパターンで、new の有る無しで結果が異なる。
検証してみる。
var b1 = Boolean()
var b2 = new Boolean()
やはり new がある場合のみ、オブジェクトが返ってきている。
さらに先に進もう。
Number オブジェクト
Number() : 新しいオブジェクトは作成されない。Numberの値が返される。(パラメーターを指定しない場合は0
)
new Number() : 新たに作成されたオブジェクトが返される。
new 有りの場合だけオブジェクトが返される。
StringとBoolean組に新たにメンバーが加わった。
検証は以下のようにコンソールに入力:
var n1 = Number()
var n2 = new Number()
n1
n2
予測どおり、n2はオブジェクトだが、n1は単なる数。
Date オブジェクト
Date() : 新しいオブジェクトは作成されない。Numberの値がStringとして返される。これはあたかもtoString()関数が呼び出された場合と同じ結果になる。
new Date() : 新たに作成されたオブジェクトが返される。
new 有りの場合だけオブジェクトが返される。
これは検証結果をよく観察しないと違いが分かりずらいかもしれない。
d1の値は""で囲まれたStringであるが赤色で表示されている。一方、d2の値はオブジェクトで、そのオブジェクトの内容が、仮にtoString()が呼び出された場合の値を表示している。
最後にError オブジェクトを調べてみる。
Error
Error() : 「new 有り」と同じ振舞をする(新たに作成されたオブジェクトが返される)。
new Error() : 新たに作成されたオブジェクトが返される。
どちらもオブジェクトが返される。
ErrorはObjectやFunctionと同じパターンで、new の有無に関わらず、新しいオブジェクトが生成される。
e1もe2もオブジェクトを指している。
#結局 new は要るの要らないの?
原則として「オブジェクトを作りたいという気持ち」があるならば new から入力し始める、というルールでOKではないだろうか?その点に関しては一貫しているので。
さて、ここまで built-in オブジェクトを使って、new 有り・無しでオブジェクトを作れるかどうかを試してきた。言語仕様に基づき、オブジェクトが作成される場合とそうでない場合があることが分かった。
だからと言って、オブジェクトを作る方法が new だけとは限らない・・・ JavaScriptの「同じ結果を出すのにいくつもの方法がある」という特徴の一つである。
#Object.create()を使ってオブジェクトを作る
JavaScriptでは
Object.create(...)
というfunctionを使ってオブジェクトを作ることが可能。