【JavaScript】 エキゾチックなオブジェクトってなに?
更新日:2022/08/10
JavaScriptにはエキゾチックなオブジェクト(exotic object)というものが存在します。
何それ?
ということで調べてみました。
Exotic Objectsとは
エキゾチックなオブジェクトとは、通常のオブジェクト(ordinary object)ではないオブジェクトを指します。
オブジェクトリテラルや、プログラムコードで定義したコンストラクターで生成されたオブジェクトなど、多くのオブジェクトは通常のオブジェクトです。
通常のオブジェクトは、プログラムから参照できない内部プロパティ(仕様上は内部スロット)を持っています。
内部プロパティには値を取得したりセットするなどの基本的なメソッドなどが定義されています。
エキゾチックなオブジェクトは、基本的なメソッドの動作を変更することで独自の動作を行う組み込みオブジェクトです。
Exotic Objectsの種類
エキゾチックなオブジェクトは全部で8種類あります。
順番に紹介します。
バインド関数エキゾチックオブジェクト
最初は、Bound Function Exotic Objectsです。
翻訳すると、バインドされた関数のエキゾチックオブジェクトとなります。
これは、関数オブジェクトのbindメソッドを実行したときに生成されるオブジェクトです。
Bound Function Exotic Objectsの使用例
const func = function(a,b){
console.log( a * b * this.d * this.e );
};
const obj = { d:1 , e:2 };
const BoundFunctionExoticObjects = func.bind( obj , 3 , 4 );
BoundFunctionExoticObjects();
// 結果: 24
バインドされた関数のエキゾチックオブジェクトは、呼び出す関数とthis値および引数を内部プロパティに保存しています。
通常の関数は、実行されると関数が持っているコードが処理されます。
バインド関数エキゾチックオブジェクトは、実行されると保存していたthis値と引数を使って関数を呼び出します。
bind()については、次のページを読んでみてください。
■【JavaScript】 今更だがbind()について理解してみる
Arrayエキゾチックオブジェクト
次はArray Exotic Objectsです。
これはArrayコンストラクターのインスタンスです。
配列リテラルから生成するケースが多いですね。
Arrayエキゾチックオブジェクトの生成
const array1 = [1,2,3]; // 配列リテラル
const array2 = new Array(1,2,3); // Arrayコンストラクター
Arrayエキゾチックオブジェクトは配列インデックスと判断できるプロパティの値が追加されたとき、インデックスが現在の lengthプロパティ 以上なら、lengthプロパティが調整されます。
また、lengthプロパティが変更されたら、その値で配列のインデックスが調整されます。
Stringエキゾチックオブジェクト
次はString Exotic Objectsです。
これはStringコンストラクターのインスタンスです。
文字列プリミティブのラッパーオブジェクトとして使用され、明示的に使用されることはほとんどありません。
文字列プリミティブのラッパーオブジェクト
const string1 = "aaa".toUpperCase();
Stringエキゾチックオブジェクトは、文字列にコードユニット単位で配列としてアクセスします。
文字列の内容は変更できません。
次のように配列として追加できますが、元の文字列を変更したわけではないです。
const s = new String("abc");
s[3] = "d";
console.log( s ); // { 0:"a" , 1:"b" , 2:"c" , 3:"d" } 一文字追加されている
console.log( s.toUpperCase() ); // "ABC" 大文字になったのは元の文字のみ
ラッパーオブジェクトについては、次のページを読んでみてください。
■【JavaScript】 プリミティブの奇妙な振る舞いとラッパーオブジェクト
コードユニットについては、次のページを読んでみてください。
■【JavaScript】 文字列データの内部形式と関連メソッドについてまとめてみた
Argumentsエキゾチックオブジェクト
Argumentsエキゾチックオブジェクトは、関数内で使用できるarguments変数の初期値です。
ただし、引数に分割代入(レスト)や初期値を指定していたり、strictモードで動作しているときは、通常のオブジェクトがarguments変数にセットされます。
引数とArgumentsエキゾチックオブジェクトは連動していて、一方が変更されると、もう一方も変更されます。
分割代入については、次のページを読んでみてください。
■【JavaScript】 コード中の「...」は意味があった スプレッド/レスト構文
Integer-Indexedエキゾチックオブジェクト
Integer-Indexedエキゾチックオブジェクトは、TypedArrayのインスタンスです。
配列インデックスとArrayBufferデータのアクセスを、上手く調整してくれます。
TypedArrayについては、次のページを読んでみてください。
■【JavaScript】 ArrayBufferとTypedArray-メモリを確保してアクセス
モジュールネームスペースエキゾチックオブジェクト
モジュールネームスペースエキゾチックオブジェクトは、export 構文でエクスポートされた関数などの参照がセットされています。
export 構文については、次のページを読んでみてください。
■【JavaScript】 export/importでモジュール化とファイル分割する方法
イミュータブルプロトタイプエキゾチックオブジェクト
イミュータブルプロトタイプエキゾチックオブジェクトは、プロトタイプへの参照を変更できないオブジェクトです。
プログラムコードでは、ほぼ意識する必要が無いオブジェクトです。
Proxyオブジェクト
Proxyオブジェクトは、既存のオブジェクトの動作を変更することができるオブジェクトです。
Proxyオブジェクトについては、次のページを読んでみてください。
■【JavaScript】 Proxyオブジェクトの使い方と仕組み
まとめ
最初はエキゾチックなオブジェクトは特殊なオブジェクトなので、プログラムではあまり使わないと思っていました。
しかし、頻繁に使う配列がエキゾチックなオブジェクトでした。
実際のところは、オブジェクトがエキゾチックかどうかは気にする必要はありません。
ほとんど役に立たない情報でしたね!
これも無駄記事になってしまうのだろうか…
更新日:2022/08/10
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。