吉本集の個人ブログ
Web制作の技術について書いています。たまに日記も書きます。

【JS入門】オブジェクトについて Vol.1(ラッパーオブジェクト)

2018年1月19日 / category : javascript

今回はオブジェクトについて深く解説していきたいと思います。前回の記事の冒頭で、JavaScript言語には定義済みのオブジェクトがたくさんあると解説しました。例えば、プログラムでよく利用する配列もオブジェクトです。

sample.js
let arr = [];
console.log( typeof arr ); // object

配列については別の機会で解説できればと思っていますが、[]で配列を定義することができます。上のコードは次のコードと同じ意味になります。

sample.js
let arr = new Array();
console.log( typeof arr ); // object

配列はArrayオブジェクトになります。new演算子+コンストラクタ関数で、インスタンスを生成するというのは前回の記事で解説しました。変数arrはインスタンスということになります。

以前の記事でプリミティブ型について解説しましたが、このプリミティブ型のデータをオブジェクトにすることができます。

sample.js
let str = '吉本';
console.log( typeof str ); // string

let obj = new String('吉本');
console.log( typeof obj ); // object

変数strはString型のデータです。JavaScriptにはString型のデータをオブジェクトにするStringオブジェクトが用意されています。変数strの値(データ)にはプリミティブ型が入っていますので、参照すると「吉本」の文字列が取得できます。それに対し、変数objはStringオブジェクトのインスタンスになりますので、そのまま参照してもStringオブジェクトが返ってきます。では、このインスタンスから「吉本」の文字列を取得するにはどうしたらよいでしょうか。

sample.js
let str = '吉本';
console.log( str ); // 吉本

let obj = new String('吉本');
console.log( obj ); // String{...}
console.log( obj.valueOf() ); // 吉本
console.log( obj.length ); // 2

上のコードを見てみます。インスタンスである変数objにvalueOfというメソッドを実行することで「吉本」の文字列を取得できることが確認できました。メソッドvalueOfはStringオブジェクトで定義されているメソッドということになります。さらにlengthというプロパティを参照することで、2という数値が取得できています。これは文字列の長さを参照するプロパティです。これもStringオブジェクトで定義されているプロパティということになります。
続いて次のコードを見てみます。

sample.js
let str = '吉本';
console.log( str ); // 吉本
console.log( str.valueOf() ); // 吉本
console.log( str.length ); // 2
console.log( typeof str ); // string

let obj = new String('吉本');
console.log( obj ); // String{...}
console.log( obj.valueOf() ); // 吉本
console.log( obj.length ); // 2
console.log( typeof obj ); // object

上のコードを見ると、プリミティブ型のデータが代入されている変数strに対し、メソッドvalueOfやプロパティlengthが定義されていることがわかります。これは一見するとおかしい挙動です。プリミティブ型のデータがプロパティを保持していることになってしまいます。

ラッパーオブジェクト

プリミティブ型のデータでString型、Number型、Boolean型、Symbol型については、それぞれラッパーオブジェクトと呼ばれるStringオブジェクト、Numberオブジェクト、Booleanオブジェクト、Symbolオブジェクトが定義されており、プロパティやメソッドを使用したタイミングで一時的にオブジェクトへ変換される仕組みになっています。あくまで一時的ですので、その後にtypeof演算子で型を調べても、プリミティブ型になることが確認できます。

sample.js
let num = 100;
console.log( num.valueOf() ); // 100

let numObj = new Number(100);
console.log( numObj.valueOf() ); // 100

let b = true;
console.log( b.valueOf() ); // true

let bObj = new Boolean(true);
console.log( bObj.valueOf() ); // true

let s = Symbol('シンボル');
console.log( s.valueOf() ); // Symbol('シンボル')

let sObj = new Symbol( Symbol('シンボル2') ); // TypeError

上のコードは、String型以外のラッパーオブジェクトの例になりますが、Symbolオブジェクトだけエラーになります。実はES6から明示的なラッパーオブジェクトの生成はサポートされていません。ただしSymbolオブジェクト以外のラッパーオブジェクトはES6以前からあったオブジェクトなので、エラーにはなりませんが、ES6以降からは推奨されないことになります。