Open9

MDN備忘録

uraura

Object.defineProperty()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
あるオブジェクトに新しいプロパティを直接定義したり、オブジェクトの既存のプロパティを変更したりして、そのオブジェクトを返す
単一のプロパティが対象

const object1 = {};

Object.defineProperty(object1, 'property1', {
  value: 42,
  writable: false,
});

object1.property1 = 77;
// Throws an error in strict mode

console.log(object1.property1);
// Expected output: 42

uraura

追加で設定できるオプションは以下

  • プロパティが変更されないように設定できる
    • writable: false 読み取り専用(既定値)
  • プロパティが for...in や Object.keys() で列挙されるかどうかを制御する
    • enumerable: false 列挙されない(既定値)
  • プロパティの削除や属性変更ができるかを制御する
    • configurable: false 削除・変更不可(既定値)
  • ゲッター・セッターの定義
uraura

例えばpageXがサポートされていない時に、clientXを使って似た機能を使うことができる

Object.defineProperty(MouseEvent.prototype, 'pageX', {
  get() {
    return this.clientX;
  }
});
uraura

Object.defineProperties()を使えば、複数のプロパティを同時に定義・変更できる

const obj = {};
Object.defineProperties(obj, {
  name: {
    value: 'Alice',
    writable: false,
    enumerable: true,
    configurable: true
  },
  age: {
    value: 30,
    writable: true,
    enumerable: false,
    configurable: true
  }
});
console.log(obj.name); // 'Alice'
console.log(obj.age);  // 30
uraura

プロパティの設定状況を確認するには、

  • Object.getOwnPropertyDescriptor()
  • Object.getOwnPropertyDescriptors()

を使う

uraura

こんな感じで使うみたい

// ベースとなるカウンター関数
function createCounter(initialValue = 0) {
  let count = initialValue;
  return function() {
    return ++count;
  };
}

// プロキシーを使用してスマートカウンターを作成
const smartCounter = new Proxy(createCounter(0), {
  // 関数として呼び出された時の処理
  apply: function(target, thisArg, args) {
    console.log('カウンターが呼び出されました');
    return target.apply(thisArg, args);
  },

  // プロパティにアクセスされた時の処理
  get: function(target, prop, receiver) {
    if (prop === 'count') {
      return target().call() - 1; // 現在のカウント値を返す
    } else if (prop === 'reset') {
      return function(value = 0) {
        console.log(`カウンターをリセットします: ${value}`);
        return createCounter(value);
      };
    }
    return Reflect.get(target, prop, receiver);
  }
});

// スマートカウンターの使用例
console.log(smartCounter()); // カウンターが呼び出されました, 1
console.log(smartCounter()); // カウンターが呼び出されました, 2
console.log(smartCounter.count); // 2
smartCounter.reset(10); // カウンターをリセットします:10
console.log(smartCounter()); // カウンターが呼び出されました, 11
console.log(smartCounter.count); // 11
uraura

Proxy

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy
元のオブジェクトからプロパティの取得、設定、定義などの基本的な Object 操作を再定義した別のオブジェクトを生成することが可能
handlerの動作を適用したtargetオブジェクトを作成(オブジェクトを拡張してる?)

uraura

Proxy は 2 つの引数で作成される

  • target: プロキシーを設定する元のオブジェクト
  • handler: どの操作に介入するか、また介入された操作をどのように再定義するかを定義するオブジェクト
const target = {
  message1: "hello",
  message2: "everyone",
};

const handler = {
  get(target, property, receiver) {
    return "world";
  },
};

// handler の動作を適用した target オブジェクトを作成
const proxy = new Proxy(target, handler);

console.log(proxy.message1); // world
console.log(proxy.message2); // world
uraura

ハンドラー関数: 対象オブジェクトの呼び出しをトラップ

  • handler.apply()は、プロキシされた関数が呼び出されたときに実行されるトラップ
  • handler.get()は、プロキシされたオブジェクトのプロパティにアクセスされたときに実行されるトラップ