JavaScript Proxy

y2sunlight 2021-07-19

ここではES2015*2015で新たに追加されたProxyオブジェクトについて説明します。

Proxyオブジェクト

Proxyを利用することで、既存のオブジェクトに手を加えずに変更することができます。

構文

new Proxy(target, handler)
    target : ラップするオブジェクト
    handler : 変更する操作を定義するためのオブジェクト(ハンドラー)

以下にメンバーの取得と設定に対する簡単なハンドラーを示します。

class Student {

    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    greeting() {
        console.log(`I am ${this.name}. I am ${this.age} years old.`);
    }
}

function createProxyStudent(name, age) {
    return new Proxy(new Student(name, age), {
        get(target, prop) {
            // メンバーが見つからない場合はそのままメンバー名を返す
            return prop in target ? target[prop] : prop;
        },

        set(target, prop, val) {
            if(prop=="age" && !Number.isInteger(val)) {
                return false;
            }
            target[prop] = val;
        }
    });
}

// オリジナルの鈴木さん
let suzuki = new Student('Suzuki', 15);
suzuki.greeting();

suzuki.age = "abc";           // I am Suzuki. I am 15 years old.
suzuki.greeting();            // I am Suzuki. I am abc years old.
console.log(suzuki.address);  // undefined


// 鈴木さんの代理人
let proxy_suzuki = createProxyStudent('Suzuki', 15);
proxy_suzuki.greeting();

proxy_suzuki.age = "abc";           // I am Suzuki. I am 15 years old.
proxy_suzuki.greeting();            // I am Suzuki. I am 15 years old.
console.log(proxy_suzuki.address);  // address

ハンドラーに定義できるハンドラーメソッドには、以下のものがあります。なお、ハンドラーメソッドはトラップとも呼ばれることがあります。

ハンドラーメソッド説明(いつ発生するか)
getプロパティ読み取り時
setプロパティ書き込み時
hasin 演算子
deletePropertydelete 演算子
apply関数呼び出し
constructnew 演算子
getPrototypeOfプロトタイプの取得
setPrototypeOfプロトタイプの設定