defineProperty【プロパティ定義 (単一)】
defineProperties【プロパティ定義 (複数)】
propertyIsEnumerable【列挙可能プロパティ 判定】

Object.defineProperty【プロパティ定義 (単一)】
Object.defineProperties【プロパティ定義 (複数)】

メモ

概要

  • プロパティを定義 (属性指定)
  • プロパティは データプロパティ または アクセサプロパティ のどちらか
    • 指定属性で判別 〔属性の組合せ
    • 共通属性以外がない場合、データプロパティ

strict モード

  • 下記は TypeError 例外
    • 書き込み不可(writable : false) プロパティで値設定
    • セッター関数未定義(set : undefined) プロパティで値設定
    • 構成変更不可(configurable : false) プロパティを削除(delete)

関連

外部リンク

構文

Object.defineProperty( O, P, Attributes ) 

 入力のO (オブジェクト)
O (Object) オブジェクト
P プロパティ名 または Symbol【シンボル】
Attributes (Object) 属性の組合せ

TypeError 例外
O (オブジェクト)がオブジェクト以外
Attributes (属性の組合せ)がオブジェクト以外
Attributes (属性の組合せ)のゲッター関数・セッター関数が呼び出し不可
Attributes (属性の組合せ)の組合せが不正
Object.defineProperties( O, Properties ) 

 入力のO (オブジェクト)
O (Object) オブジェクト
Properties (Object) プロパティ定義 (以下のオブジェクト)
キー: プロパティ名 または Symbol【シンボル】
値: 属性の組合せ

TypeError 例外
O (オブジェクト)がオブジェクト以外
属性の組合せのゲッター関数・セッター関数が呼び出し不可
属性の組合せが不正

属性の組合せ

(データプロパティのみ または アクセサプロパティのみ が有効)

属性デフォルト値データ
プロパティ
アクセサ
プロパティ
備考
valueundefined
getundefinedゲッター関数 (引数:なし)
setundefinedセッター関数 (引数:値)
writablefalse書き込みの可否
enumerablefalseプロパティ列挙の可否
configurablefalse構成変更の可否
true の場合、下記が可能
・プロパティの削除
・データプロパティ と アクセサプロパティ の切換
・属性変更 (value・writable 以外も)

例:Object.defineProperty【プロパティ定義 (単一)】

const obj = { propA: 'ValuePropA' };
console.log(Object.getOwnPropertyDescriptor(obj, 'propA'));
// 出力:Object { value: "ValuePropA", writable: true, enumerable: true, configurable: true }
obj.propB = 'ValuePropB';
console.log(Object.getOwnPropertyDescriptor(obj, 'propB'));
// 出力:Object { value: "ValuePropB", writable: true, enumerable: true, configurable: true }

// デフォルト (データプロパティ)
Object.defineProperty(obj, 'propDefault', { value: 'ValueDefault' });
console.log(Object.getOwnPropertyDescriptor(obj, 'propDefault'));
// 出力:Object { value: "ValueDefault", writable: false, enumerable: false, configurable: false }
obj.propDefault = 'Dummy'; // 値変更 (失敗:エラーなし)
console.log(obj.propDefault);
// 出力:ValueDefault
(function() {
  'use strict';
  // obj.propDefault = 'Dummy'; // 値変更 (失敗:例外)
  // TypeError: "propDefault" is read-only
}());
console.log(Object.keys(obj)); // 列挙 (対象外)
// 出力:Array [ "propA", "propB" ]
// Object.defineProperty(obj, 'propDefault', { writable: true });  // 属性変更 (失敗)
// TypeError: can't redefine non-configurable property "propDefault"
delete obj.propDefault; // 削除 (失敗)
console.log(obj.propDefault);
// ValueDefault

// 書き込み可 (データプロパティ)
Object.defineProperty(obj, 'propWritable', { value: 'ValueWritable', writable: true });
console.log(Object.getOwnPropertyDescriptor(obj, 'propWritable'));
// 出力:Object { value: "ValueWritable", writable: true, enumerable: false, configurable: false }
obj.propWritable = 'ValueWritable_New'; // 値変更 (成功)
console.log(obj.propWritable);
// 出力:ValueWritable_New
console.log(Object.keys(obj)); // 列挙 (対象外)
// 出力:Array [ "propA", "propB" ]
delete obj.propWritable; // 削除 (失敗:エラーなし)
(function() {
  'use strict';
  // delete obj.propWritable; // 削除 (失敗:例外)
  // TypeError: property "propWritable" is non-configurable and can't be deleted
}());
console.log(obj.propWritable);
// 出力:ValueWritable_New
// Object.defineProperty(obj, 'propWritable', { enumerable: true }); // 属性変更 (失敗)
// TypeError: can't redefine non-configurable property "propWritable"

// シンボル・列挙可 (データプロパティ)
const symbolEnumerable = Symbol('enumerable');
Object.defineProperty(obj, symbolEnumerable, { value: 'ValueEnumerable', enumerable: true });
console.log(Object.getOwnPropertyDescriptor(obj, symbolEnumerable));
// 出力:Object { value: "ValueEnumerable", writable: false, enumerable: true, configurable: false }
obj[symbolEnumerable] = 'Dummy'; // 値変更 (失敗:エラーなし)
(function() {
  'use strict';
  // obj[symbolEnumerable] = 'Dummy'; // 値変更 (失敗:例外)
  // TypeError: Symbol("enumerable") is read-only
}());
console.log(obj[symbolEnumerable]);
// 出力:ValueEnumerable
console.log(Object.keys(obj)); // 列挙 (対象)
// 出力:Array(3) [ "propA", "propB", "propEnumerable" ]
delete obj[symbolEnumerable]; // 削除 (失敗:エラーなし)
(function() {
  'use strict';
  // delete obj[symbolEnumerable]; // 削除 (失敗:例外)
  // TypeError: property Symbol("enumerable") is non-configurable and can't be deleted
}());
console.log(obj[symbolEnumerable]);
// 出力:ValueEnumerable
// Object.defineProperty(obj, symbolEnumerable, { enumerable: false }); // 属性変更 (失敗)
// TypeError: can't redefine non-configurable property Symbol("enumerable")

// 構成変更可 (データプロパティ)
Object.defineProperty(obj, 'propConfigurable', { value: 'ValueConfigurable', configurable: true });
console.log(Object.getOwnPropertyDescriptor(obj, 'propConfigurable'));
// 出力:Object { value: "ValueConfigurable", writable: false, enumerable: false, configurable: true }
obj.propConfigurable = 'Dummy'; // 値変更 (失敗:エラーなし)
(function() {
  'use strict';
  // obj.propConfigurable = 'Dummy'; // 値変更 (失敗:例外)
  // TypeError: "propConfigurable" is read-only
}());
console.log(obj.propConfigurable);
// 出力:ValueConfigurable
console.log(Object.keys(obj)); // 列挙 (対象外)
// 出力:Array(3) [ "propA", "propB", "propEnumerable" ]
Object.defineProperty(obj, 'propConfigurable', { enumerable: true }); // 属性変更 (成功)
console.log(Object.getOwnPropertyDescriptor(obj, 'propConfigurable'));
// 出力:Object { value: "ValueConfigurable", writable: false, enumerable: true, configurable: true }
delete obj.propConfigurable; // 削除 (成功)
console.log(obj.propConfigurable);
// 出力:undefined

// 各種例外
// O (オブジェクト)がオブジェクト以外
// Object.defineProperty(undefined, 'propDummy', { value: 'ValueDummy' });
// TypeError: undefined is not a non-null object
// Attributes (属性の組合せ)がオブジェクト以外
// Object.defineProperty(obj, 'propDummy', undefined);
// TypeError: Property descriptor must be an object, got undefined
// Attributes (属性の組合せ)のゲッター関数・セッター関数が呼び出し不可
// Object.defineProperty(obj, 'propDummy', { get: null});
// TypeError: property descriptor's get field is neither undefined nor a function
// Attributes (属性の組合せ)の組合せが不正
// Object.defineProperty(obj, 'propDummy', { value: 'ValueDummy', get: function() {return 'Dummy';}});
// TypeError: property descriptors must not specify a value or be writable when a getter or setter has been specified

// ゲッター関数・セッター関数 (アクセサプロパティ)
function getAccessorObj(value) {
  let _value = value;
  const obj = { };
  Object.defineProperty(
    obj,
    'propSetterGetter',
    {
      get: function() { return _value + ' (Getter)'; },
      set: function(value) { _value = value; }
    }
  );
  return obj;
}
const objAcc = getAccessorObj('Value');
console.log(Object.getOwnPropertyDescriptor(objAcc, 'propSetterGetter'));
// 出力:Object { get: get(), set: set(value), enumerable: false, configurable: false }
console.log(objAcc.propSetterGetter);
// 出力:Value (Getter)
objAcc.propSetterGetter = 'Value_NEW';
console.log(objAcc.propSetterGetter);
// 出力:Value_NEW (Getter)
console.log(Object.keys(objAcc)); // 列挙 (対象外)
// 出力:Array []
delete objAcc.propSetterGetter; // 削除 (失敗:エラーなし)
(function() {
  'use strict';
  // delete objAcc.propSetterGetter; // 削除 (失敗:例外)
  // TypeError: property "propSetterGetter" is non-configurable and can't be deleted
}());
console.log(objAcc.propSetterGetter);
// 出力:Value_NEW (Getter)
// Object.defineProperty(objAcc, 'propSetterGetter', { enumerable: true }); // 属性変更 (失敗)
// TypeError: can't redefine non-configurable property "propSetterGetter"

// ゲッター関数のみ (アクセサプロパティ)
Object.defineProperty(objAcc, 'propNonSetter', { get: function() { return '(Getter)'; } });
console.log(Object.getOwnPropertyDescriptor(objAcc, 'propNonSetter'));
// 出力:Object { get: get(), set: undefined, enumerable: false, configurable: false }
objAcc.propNonSetter = 'Dummy'; // 値変更 (失敗:エラーなし)
(function() {
  'use strict';
  // objAcc.propNonSetter = 'Dummy'; // 値変更 (失敗:例外)
  // TypeError: setting getter-only property "propNonSetter"
}());
console.log(objAcc.propNonSetter);
// 出力:(Getter)

例:Object.defineProperties【プロパティ定義 (複数)】

const obj = { };
const symbolWritable = Symbol('Writable');
Object.defineProperties(
  obj,
  {
     'prop': { value: 'Value' },
     symbolWritable: { value: 'ValueWritable', writable: true },
     'propEnumerable': { value: 'ValueEnumerable', enumerable: true },
     'propConfigurable': { value: 'ValueConfigurable', configurable: true },
     'propSetterGetter': { get: function() { return '(Getter)'; }, set: function(value) { }},
  }
);
console.log(Object.getOwnPropertyDescriptors(obj));
// 出力:
// Object { prop: {…}, symbolWritable: {…}, propEnumerable: {…}, propConfigurable: {…}, propSetterGetter: {…} }
//   prop: Object { value: "Value", writable: false, enumerable: false, … }
//     configurable: false
//     enumerable: false
//     value: "Value"
//     writable: false
//   propConfigurable: Object { value: "ValueConfigurable", writable: false, enumerable: false, … }
//     configurable: true
//     enumerable: false
//     value: "ValueConfigurable"
//     writable: false
//   propEnumerable: Object { value: "ValueEnumerable", writable: false, enumerable: true, … }
//     configurable: false
//     enumerable: true
//     value: "ValueEnumerable"
//     writable: false
//   propSetterGetter: Object { get: get(), enumerable: false, configurable: false, … }
//     configurable: false
//     enumerable: false
//     get: function get()​​
//     set: function set(value)
//   symbolWritable: Object { value: "ValueWritable", writable: true, enumerable: false, … }
//     configurable: false
//     enumerable: false
//     value: "ValueWritable"
//     writable: true

console.log(Object.getOwnPropertyNames(obj));
// 出力:Array(5) [ "prop", "symbolWritable", "propEnumerable", "propConfigurable", "propSetterGetter" ]

console.log(Object.keys(obj));
// 出力:Array [ "propEnumerable" ]
for (const key in obj) {
  console.log(key);
}
// 出力:
// propEnumerable

Object.prototype.propertyIsEnumerable【列挙可能プロパティ 判定】

メモ

概要

  • プロパティが列挙可能か判定

関連

外部リンク

構文

Object.propertyIsEnumerable( V )

 プロパティの列挙可能 判定 (true:列挙可 / :false列挙不可)
V プロパティ名

const obj = { propEnum: 'ValueEnum' };
Object.defineProperty(obj, 'propUnenum', { value: 'ValueUnenum', enumerable: false });
console.log(Object.getOwnPropertyDescriptor(obj, 'propEnum'));
// 出力:Object { value: "ValueEnum", writable: true, enumerable: true, configurable: true }
console.log(obj.propertyIsEnumerable('propEnum'));
// 出力:true
console.log(Object.getOwnPropertyDescriptor(obj, 'propUnenum'));
// 出力:Object { value: "ValueUnenum", writable: false, enumerable: false, configurable: false }
console.log(obj.propertyIsEnumerable('propUnenum'));
// 出力:false