JavaSciriptのプロパティとディスクリプターについて

JavaScript

JavaSciriptのプロパティとディスクリプターについてまとめました。

プロパティとディスクリプター

オブジェクトを作成するとプロパティには、値(バリュー)がセットされます。
実は、この値以外にもプロパティの設定値を保持しています。

  • configurable
  • enumerable
  • writable

という3つを保持しています。
値を含めて上の4つをディスクリプターといいます。
これらの値を設定することで、プロパティの挙動を調整することができます。

プロパティの設定値

プロパティの設定値
value
configurable 設定変更の可否
enumarable 列挙の可否
writable 値の変更の可否

ディスクリプターの設定

const a = { p: 0 };
const descriptor = Object.getOwnPropertyDescriptor(a, 'p');
console.log(descriptor);
// {value: 0, 
// writable: true, 
// enumerable: true, 
// configurable: true}

getOwnPropertyDescriptorでディスクリプターの設定をみることができます。
このように、オブジェクトリテラルで定義すると、すべてtrueで設定されていることがわかります。
プロパティの設定を変更してみます。
definePropertyで設定を変更することができます。

const b = {};
Object.defineProperty(b, 'p', {
  value: 9,
  writable: true,
});
const descriptor = Object.getOwnPropertyDescriptor(b, 'p');
// {value: 9, 
// writable: true, 
// enumerable: false, 
// configurable: false}
b.p = 1;
console.log(descriptor);
console.log(b.p); //1

それぞれのプロパティには、ディスクリプターがあり、ディスクリプターの設定によって挙動が異なっているということを知っておくことが重要です。

setとgetを設定する

ディスクリプターで、setとgetを設定できます。
setとgetはオプションなので、設定されない場合はundefinedになります。
setとgetを設定すると特別な機能を追加することが可能です。
ディスクリプターで設定されるsetとgetのことをsetterとgetterといいます。

function Student(name, age) {
  this._name = name;
  this._age = age;
}

Object.defineProperty(Student.prototype, 'rename', {
  get: function () {
    console.log('こんにちは');
    return `${this._name}さん`;
  },
  set: function (val) {
    this._name = val;
  },
});

const yamada = new Student('yamada', 40);
console.log(yamada.rename);
// こんにちは
// yamadaさん
console.log(yamada._name); //yamada

definePropertyでは、第一引数にディスクリプターを使って設定したいオブジェクトを渡します。
第二引数にgetとsetで使いたい値を指定します。そして、getとsetを設定します。
getには呼ばれた際の動作を書きます。
設定したプロパティに値を取りにいくようなことをするとgetが呼び出されます。
setは引数に設定された値が入ってきます。

yamada.rename = '山田';
console.log(yamada.rename);
// こんにちは
// 山田さん
console.log(yamada._name); //山田

getが呼ばれるたびに必ずgetterの関数が実行されることになるので、なんらかの処理をgetとsetをいれることができます。

同じことをES6のクラスを使うと次のように記述することができます。

class Student2 {
  constructor(name, age) {
    this._name = name;
    this._age = age;
  }
  get rename() {
    console.log('こんにちは');
    return `${this._name}さん`;
  }
  set rename(val) {
    this._name = val;
  }
}

具体的なgetterとsetterの例はこちらを参考にしてみてください。