JavaScriptは対象を深く理解する方法——Object.defineProperties()


Object.defineProperties()Object.defineProperties()方法は、オブジェクトに直接に新しい属性を定義したり、既存の属性を変更したりして、オブジェクトに戻ります.
構文Object.defineProperties(obj, props)パラメータ
  • objは、属性のオブジェクトを定義または変更する.
  • propsは、列挙属性または修正可能な属性記述子のオブジェクトを定義する.オブジェクトに存在する属性記述子は主に2つあります.データ記述子とアクセス記述子(詳細はObject.defineProperty()を参照してください.ディスクリプタは以下のキーを持っています.
  • configrable trueは、属性記述子のタイプのみが変更され、対応するオブジェクトから属性を削除することができる.デフォルトはfalse
  • です.
  • enumerable trueは、エニュメレート・オブジェクト上の属性のみが存在する場合に、この属性が表示される.デフォルトはfalse
  • です.
  • valueと属性関連の値.任意の有効なJavaScript値(数字、オブジェクト、関数など)とすることができます.デフォルトはundefinedです.
  • です.
  • writable trueが、この属性に関連する値がassignment operatorで変更される場合にのみ使用されます.デフォルトはfalse
  • です.
  • getは、この属性のgetter関数として、getterがなければundefinedとなる.関数の戻り値は属性の値として使用されます.デフォルトはundefined
  • です.
  • setは属性のsetter関数として、setterがなければundefinedとなる.関数は、属性の新しい値にパラメータのみの割り当てを受け付けます.デフォルトはundefined
  • です.
    戻り値
    関数のオブジェクトに渡す.
    説明Object.definePropertiesは、Objオブジェクト上のpropsのエニュメレート・属性に対応するすべての属性を本質的に定義している.
    var obj = {};
    Object.defineProperties(obj, {
      'property1': {
        value: true,
        writable: true
      },
      'property2': {
        value: 'Hello',
        writable: false
      }
      // etc. etc.
    });
    Polyfill
    元の実行環境を仮定すると、すべての名称と属性はそれらの初期値を参照し、Object.definePropertiesはほぼ完全に(注意isCallableにおける注釈)以下のJavaScriptの中の再実現に等しい.
    function defineProperties(obj, properties) {
      function convertToDescriptor(desc) {
        function hasProperty(obj, prop) {
          return Object.prototype.hasOwnProperty.call(obj, prop);
        }
    
        function isCallable(v) {
          // NB: modify as necessary if other values than functions are callable.
          return typeof v === 'function';
        }
    
        if (typeof desc !== 'object' || desc === null)
          throw new TypeError('bad desc');
    
        var d = {};
    
        if (hasProperty(desc, 'enumerable'))
          d.enumerable = !!desc.enumerable;
        if (hasProperty(desc, 'configurable'))
          d.configurable = !!desc.configurable;
        if (hasProperty(desc, 'value'))
          d.value = desc.value;
        if (hasProperty(desc, 'writable'))
          d.writable = !!desc.writable;
        if (hasProperty(desc, 'get')) {
          var g = desc.get;
    
          if (!isCallable(g) && typeof g !== 'undefined')
            throw new TypeError('bad get');
          d.get = g;
        }
        if (hasProperty(desc, 'set')) {
          var s = desc.set;
          if (!isCallable(s) && typeof s !== 'undefined')
            throw new TypeError('bad set');
          d.set = s;
        }
    
        if (('get' in d || 'set' in d) && ('value' in d || 'writable' in d))
          throw new TypeError('identity-confused descriptor');
    
        return d;
      }
    
      if (typeof obj !== 'object' || obj === null)
        throw new TypeError('bad obj');
    
      properties = Object(properties);
    
      var keys = Object.keys(properties);
      var descs = [];
    
      for (var i = 0; i < keys.length; i++)
        descs.push([keys[i], convertToDescriptor(properties[keys[i]])]);
    
      for (var i = 0; i < descs.length; i++)
        Object.defineProperty(obj, descs[i][0], descs[i][1]);
    
      return obj;
    }