KDE BLOG

Webデザインやコーディングについて書いています

【JavaScript基礎】オブジェクトは常に動的である

<目次>

JavaScriptではいつでもオブジェクトにプロパティやメソッドを追加できる

JavaScriptのオブジェクトは常に動的であるため、オブジェクトへのあらゆる変更が許可されています。
それは組み込みオブジェクトでさえもです。

const now = new Date();
console.log(now.toString()); // Tue Jun 06 2017 01:05:29 GMT+0900 (東京 (標準時))

now.toString = 1;
console.log(now.toString); // 1

上記では、組み込みオブジェクトであるDateオブジェクトの、オブジェクトを表す文字列を返すtoStringメソッドを、途中から数値の「1」を上書きしました。
そのためあっさりとtoStringメソッドの機能はなくなりました。

このようにネイティブの組み込みオブジェクトでさえ簡単に変更が可能です。
※実際のコーディングでは組み込みオブジェクトのプロパティやメソッドを変更するのは混乱のもとになるのでやめておくべきです。
実際にはnew演算子リテラル表現で作成されたインスタンスのオブジェクトに対してプロパティやメソッドを追加するのが一般的です。
つまりインスタンスは自身のプロパティ、メソッドを持つことができます。
それぞれインスタンスプロパティ、インスタンスメソッドと呼びます。

※プリミティブ値にはプロパティ、メソッドの追加はできません。

const myString = new String();
myString.prop = 'test';

const myNumber = new Number();
myNumber.prop = 'test';

const myBoolean = new Boolean();
myBoolean.prop = 'test';

const myObject = {};
myObject.prop = 'test';

const myArray = [1,2,3];
myArray.prop = 'test';

const myFunc = new Function();
myFunc.prop = 'test';

const myRegExp = new RegExp('\bt[a-z]+\b');
myRegExp.prop = 'test';

const myError = new Error('a');
myError.prop = 'test';

console.log(
    // すべて'test'
    myString.prop,
    myNumber.prop,
    myBoolean.prop,
    myObject.prop,
    myArray.prop,
    myFunc.prop,
    myRegExp.prop,
    myError.prop
);

// プリミティブ値
const myString2 = 'Hi!';
myString2.prop = 'test';

const myNumber2 = 10;
myNumber.prop = 'test';

const myBoolean2 = true;
myBoolean.prop = 'test';

console.log(
    // すべて'undefined'
    myString2.prop,
    myNumber2.prop,
    myBoolean2.prop
);

インスタンスは自身のプロパティの他に、プロトタイプチェーンから継承したプロパティも保持できます。(プロトタイプチェーンについては後日まとめます)

オブジェクトのプロパティにはどんな値も格納できる

オブジェクトは非常に柔軟で、下記に示すようにどんな型の値も格納できます
関数オブジェクトや配列オブジェクトも同様で、String()、Number()、Boolean()のコンストラクタ関数から生成されたオブジェクトのプロパティも同様です。

const myObject = {
    myFunction : function() {},
    myString   : 'Hello.',
    myNumber   : 10,
    myBoolean  : true,
    myUndefined: undefined,
    myNull     : null,
    myArray    : [],
    myDate     : new Date(),
    myRegExp   : /a/,
    myObject   : {},
    myMath     : Math.PI,
    myError    : new Error('Error!')
};

console.log(
    // すべて設定した値が出力される
    myObject.myFunction,
    myObject.myString,
    myObject.myNumber,
    myObject.myBoolean,
    myObject.myUndefined,
    myObject.myNull,
    myObject.myArray,
    myObject.myDate,
    myObject.myRegExp,
    myObject.myObject,
    myObject.myMath,
    myObject.myError
);

オブジェクトのプロパティを削除するにはdelete演算子を使う

オブジェクトのプロパティを削除する唯一の方法がdelete演算子です。

下記ではdelete演算子を使ってmyObjectのaプロパティを削除後、in演算子でaプロパティが存在しているか判定しています。結果はfalseを返しています。

delete演算子にはいくつか注意があります。

  • 指定されたオブジェクトのプロパティのみを削除する。プロトタイプチェーンで継承するプロパティは削除しない。
  • varなどで宣言した変数、function宣言した関数は削除できません。
  • 定義済みのプロパティは削除できません。例)delete Math.PI; // 削除できずfalseを返します。
const myObject = {
    a: 1,
    b: function() {}
};

delete myObject.a;

console.log('a' in myObject); // false (in演算子は左辺のプロパティが右辺に存在するかの真偽値を返します)

詳しくはMDNをご確認ください。

参考

開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質

開眼! JavaScript ―言語仕様から学ぶJavaScriptの本質