3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ES5 プロパティの属性について

Posted at

めもです。

がいよう

オブジェクトの各プロパティには以下の属性がある。

  • データプロパティのみ
  • [[Value]]
  • [[Writable]]
  • アクセサープロパティのみ
  • [[Get]]
  • [[Set]]
  • 全プロパティ共通
  • [[Enumerable]]
  • [[Configurable]]

プロパティ属性の取得

Object.getOwnPropertyDescriptor(object, propertyName) を使う。戻り値の value[[Value]] に、writable[[Writable]] に、以下同様、対応している。

Object.getOwnPropertyDescriptor(window, 'NaN');
// => {value: NaN, writable: false, enumerable: false, configurable: false}

プロパティ属性の設定

主にObject.defineProperty(object, propertyName, descriptor)を使う。省略した属性の値は falseundefined になる。

Object.defineProperty(document, 'myProperty', {
  writable: true,
  enumerable: true,
});
Object.getOwnPropertyDescriptor(document, 'myProperty');
// => {value: undefined, writable: true, enumerable: true, configurable: false}

データプロパティの [[Value]] と [[Writable]]

データプロパティは [[Value]][[Writable]] のどちらかがある (undefinedでない) プロパティのこと。 obj.face = 'ヮ' など普通に代入するとこれになる。

[[Value]]

プロパティの値。

var obj = {};
obj.face = 'ω';
Object.getOwnPropertyDescriptor(obj, 'face');
// => {value: "ω", writable: true, enumerable: true, configurable: true}

[[Writable]]

プロパティの値を変更できるかどうか。
[[Writable]] でないプロパティに代入すると、strict モードなら TypeError 例外が投げられ、そうでなければ無視される。

var obj = {};
Object.defineProperty(obj, 'face', {
  value: '',
  writable: false,
});
obj.face = '';
console.log(obj.face); // => ᴗ
(function() {
  "use strict";
  obj.face = ''; // => TypeError!
})();

アクセサープロパティの [[Get]] と [[Set]]

アクセサープロパティは [[Get]][[Set]] のどちらかがある (undefinedでない) プロパティのこと。

[[Get]]

引数を受け取らない関数。プロパティの値を取得する時に呼ばれる。

var obj = {};
Object.defineProperty(obj, 'name', {
  get: function() { return '坂上陽三'; }
});
console.log(obj.name); // => 坂上陽三

[[Set]]

引数を1個受け取る関数。プロパティに値を割り当てる時に呼ばれる。

var obj = {};
Object.defineProperty(obj, 'name', {
  get: function() { return '坂上陽三'; }
});
console.log(obj.name); // => 坂上陽三

[[Enumerable]]

for in や Object.keys で列挙されるかどうか。

var obj = {};
Object.defineProperty(obj, 'visible', {
  enumerable: true,
});
Object.defineProperty(obj, 'hidden', {
  enumerable: false,
});
Object.keys(obj); // => ["visible"]

[[Configurable]]

[[Configure]] === false だと

  • プロパティを削除できない
  • [[Value]] 以外の属性を変更できない
var obj = {};
Object.defineProperty(obj, 'x', {
  configurable: false,
});
delete obj.x; // => false
Object.defineProperty(obj, 'x', {writable: true}); // => TypeError!
Object.defineProperty(obj, 'x', {enumerable: true}); // => TypeError!
Object.defineProperty(obj, 'x', {configurable: true}); // => TypeError!
Object.defineProperty(obj, 'x', {get: Date.now}); // => TypeError!
Object.defineProperty(obj, 'x', {set: alert.bind(window)}); // => TypeError!
Object.defineProperty(obj, 'x', {value: 'y'}); // => ok
Object.x = 'X'; // => ok

ついでにオブジェクトの [[Extensible]]

オブジェクトの [[Extensible]] 属性が false だとプロパティを追加できない。
Object.preventExtensionsObject.isExtensible を使ってアクセスする。

var obj = {};
Object.isExtensible(obj); // => true
obj.x = 'x';
Object.preventExtensions(obj);
Object.isExtensible(obj); // => false
obj.y = 'y';
obj.y; // => undefined
(function() {
  "use strict";
  obj.y = 'y'; // => TypeError!
})();

属性をまとめて false にするメソッド

  • Object.seal
  • Object.freeze

Object.seal(あざらし)あざらし[[Extensible]]false にし、各プロパティの [[Configurable]]false にする。

Object.freeze(あざらし)Object.seal の処理に加えて、あざらしの各プロパティの[[Writable]]false にする。

たとえば配列を seal すると固定長になり、freeze すると不変になる。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?