この解答例はChatGPTによって生成されています,正しいかは自己判断で。

BFE.devでのAI解答例 - JavaScript コーディング問題
27. completeAssign() を実装する

解法:

completeAssign()の実装には、Object.getOwnPropertyDescriptor()Object.defineProperty()を使う必要があります。Object.getOwnPropertyDescriptor()は、オブジェクトのプロパティのdescriptorを返します。Object.defineProperty()は、オブジェクトに新しいプロパティを追加または既存のプロパティを変更するために使用されます。

以下は、completeAssign()の実装です。

function completeAssign(target, ...sources) {
  sources.forEach(source => {
    Object.getOwnPropertyNames(source).forEach(propName => {
      Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName));
    });
    Object.getOwnPropertySymbols(source).forEach(propSymbol => {
      Object.defineProperty(target, propSymbol, Object.getOwnPropertyDescriptor(source, propSymbol));
    });
  });
  return target;
}

この実装では、まずsourcesから1つずつオブジェクトを取り出し、Object.getOwnPropertyNames()Object.getOwnPropertySymbols()を使って、オブジェクトのすべてのプロパティの名前とSymbolを取得します。次に、各プロパティのdescriptorをObject.getOwnPropertyDescriptor()を使って取得し、Object.defineProperty()を使って、targetオブジェクトに追加または変更します。

以下は、これを実際に使った例です。

const source = Object.create(
  {
    a: 3 // prototype
  },
  {
    b: {
      value: 4,
      enumerable: true // 列挙可能なdata descriptor
    },
    c: {
      value: 5, // 枚举不可なdata descriptor
    },
    d: { // 枚举不可なaccessor descriptor 
      get: function() {
        return this._d;
      },
      set: function(value) {
        this._d = value
      }
    },
    e: { // 列挙可能な accessor descriptor 
      get: function() {
        return this._e;
      },
      set: function(value) {
        this._e = value
      },
      enumerable: true
    }
  }
);

const result = completeAssign({}, source);

console.log(result); // { b: 4, c: 5, d: undefined, e: undefined }

この例では、sourceオブジェクトからtargetオブジェクトにプロパティがコピーされ、bcdeがtargetオブジェクトに保存されます。deは、Object.getOwnPropertyDescriptor()を使用して、getterおよびsetterを保持しているため、間違った値を保持することはありません。