ES6 のプロキシの詳細な分析

青灯夜游
リリース: 2021-07-05 11:23:25
転載
1693 人が閲覧しました

ES6 のプロキシの詳細な分析

単純なプロキシの作成

let target = {}
let proxy = new Proxy(target, {})

proxy.name = 'proxy'

console.log(proxy.name) // proxy
console.log(target.name) // proxy

target.name = 'target'

console.log(proxy.name) // target
console.log(target.name) // target
ログイン後にコピー

このインスタンスは、「プロキシ」を proxy.name 属性に割り当てるときに、ターゲット上に名前を作成します。プロキシは単純に「転送」を実行します。ターゲットの場合、この属性は保存されません。 proxy.name と target.name に相当するものは、target.name の値を参照します。

set トラップを使用してプロパティを確認する

set トラップは 4 つのパラメータを受け取ります:

1.trapTarget: プロパティ (エージェントのターゲット) を受け取るために使用されるオブジェクト

2.key: 書き込まれる属性キー (文字列または記号)

3.value: 書き込まれる属性値

4.receiver: 操作が発生するオブジェクト(通常はプロキシ)

let target = {
    name: "target"
}

let proxy = new Proxy(target, {
    set(trapTarget, key, value, receiver) {
        if (!trapTarget.hasOwnProperty(key)) {
            if (isNaN(value)) {
                throw new TypeError("属性必须时数字")
            }
        }

        return Reflect.set(trapTarget, key, value, receiver)
    }
})

proxy.count = 1
console.log(proxy.count) //1
console.log(target.count) //1

proxy.name = "proxy"

console.log(proxy.name) //proxy
console.log(target.name) //proxy

proxy.other = "other" // 这里会报错因为不数字
ログイン後にコピー

このインスタンスは、プロキシの値が外部で変更されるたびに set 関数をトリガーします。

get トラップを使用してオブジェクト構造を確認します

get は 3 つのパラメータを受け取ります

1.trapTarget: 属性 (エージェントのターゲット) を受け取るために使用されるオブジェクト

2.key: 書き込まれる属性キー (文字列または記号)

3.receiver: 操作が行われるオブジェクト (通常はプロキシ)

let proxy = new Proxy({}, {
    get(trapTarget, key, receiver) {
        if (!(key in receiver)) {
            throw new TypeError("属性" + key + "不存在")
        }

        return Reflect.get(trapTarget, key, receiver)
    }
})

proxy.name = "proxy"

console.log(proxy.name) //proxy

console.log(proxy.age) // 属性不存在会抛出错误
ログイン後にコピー

プロキシによって作成されたオブジェクトのプロパティ get メソッドがトリガーされます

use にはトラップがあるため、既存の属性があります

has は 2 つのパラメータを受け取ります:

1.trapTarget: を受け取るために使用されます属性 (エージェントのターゲット) Object

2.key: 書き込まれるプロパティ キー (文字列またはシンボル)

let target = {
    name: "target",
    value: 42
}

let proxy = new Proxy(target, {
    has(trapTarget, key) {
        if (key === 'value') {
            return false
        } else {
            return Reflect.has(trapTarget, key)
        }
    }
})


console.log("value" in proxy) // false
console.log("name" in proxy) // true
console.log("toString" in proxy) // true
ログイン後にコピー

プロパティの削除を防ぐために deleteProperty トラップを使用します

deleteProperty は 2 つのパラメータを受け取ります:

1.trapTarget: 属性 (エージェントのターゲット) を受け取るために使用されるオブジェクト

2.key: 書き込まれる属性キー (文字列またはシンボル)

let target = {
    name: "target",
    value: 42
}

let proxy = new Proxy(traget, {
    deleteProperty(trapTarget, key) {
        if (key === "value") {
            return false
        } else {
            return Reflect.deleteProperty(trapTarget, key)
        }
    }
})


console.log("value" in proxy) // true

let result1 = delete proxy.value

console.log(result1) // false
console.log("value" in proxy) // true

console.log("name" in proxy) // true

let result2 = delete proxy.name
console.log(result2) // true
console.log("name" in proxy) // false
ログイン後にコピー

When プロキシの属性を外部から削除する場合、deleteProperty 関数がトリガーされます。

プロトタイプ プロキシ トラップ (setProptotypeOf、getPrototypeOf)

setProptotypeOf は 2 つのパラメータを受け取ります

1.trapTarget: 属性を受け取るために使用されます (プロキシのターゲット)

#2.proto: プロトタイプとして使用されるオブジェクト

let target = {}

let proxy = new Proxy(target, {

    // 访问时调用
    getPrototypeOf(trapTarget) {
        return null
    },
    // 改变时调用
    setPrototypeOf(trapTarget, proto) {
        return false
    }

})

let targetProto = Object.getPrototypeOf(target)
let proxyProto = Object.getPrototypeOf(proxy)

console.log(targetProto === Object.prototype) //true
console.log(proxyProto === Object.prototype) // false
console.log(proxyProto) // null

Object.setPrototypeOf(target, {}) // 成功

Object.setPrototypeOf(proxy, {}) // 抛出错误
ログイン後にコピー

正常に実装された場合

let target = {}

let proxy = new Proxy(target, {

    // 访问时调用
    getPrototypeOf(trapTarget) {
        return Reflect.getPrototypeOf(trapTarget)
    },
    // 改变时调用
    setPrototypeOf(trapTarget, proto) {
        return Reflect.setPrototypeOf(trapTarget, proto)
    }

})

let targetProto = Object.getPrototypeOf(target)
let proxyProto = Object.getPrototypeOf(proxy)

console.log(targetProto === Object.prototype) //true
console.log(proxyProto === Object.prototype) // true

Object.setPrototypeOf(target, {}) // 成功

Object.setPrototypeOf(proxy, {}) // 成功
ログイン後にコピー

プロパティ記述子trap

defineProperty 3つのパラメータを受け取ります:

1.trapTarget: 属性(エージェントのターゲット)を受け取るために使用されるオブジェクト

2.key:書き込む属性キー (文字列または記号)

3.descriptor: プロパティの説明オブジェクト

let proxy = new Proxy({}, {
    defineProperty(trapTarget, key, descriptor) { // descriptor 只能接收enumerable, configurable, value, writeable, get, set 
        if (typeof key === "symbol") {
            return false
        }
        return Reflect.defineProperty(trapTarget, key, descriptor)
    },
    getOwnPropertyDescriptor(trapTarget, key) {
        return Reflect.getOwnPropertyDescriptor(trapTarget, key)
    }
})

Object.defineProperty(proxy, "name", {
    value: "proxy"
})

console.log(proxy.name) //proxy

let nameSymbol = Symbol("name")

Object.defineProperty(proxy, nameSymbol, {
    value: "proxy"
})
ログイン後にコピー

内部のdefineProperty | getOwnPropertyDescriptor メソッドは、defineProperty | getOwnPropertyDescriptor が外部から呼び出されたときにトリガーされます。

ownKeys トラップ

ownKeys トラップは、4 つの外部メソッド Object.keys()、Object.getOwnPropertyName()、Object.getOwnPropertySymbols()、および Object.assign()

let proxy = new Proxy({}, {
    ownKeys(trapTarget) {
        return Reflect.ownKeys(trapTarget).filter(key => {
            return typeof key !== "string" || key[0] !== '_'
        })
    }
})

let nameSymbol = Symbol("name")

proxy.name = "proxy"

proxy._name = "private"

proxy[nameSymbol] = "symbol"

let names = Object.getOwnPropertyNames(proxy),
    keys = Object.keys(proxy),
    symbols = Object.getOwnPropertySymbols(proxy)

console.log(names.length) // 1
console.log(names) // name

console.log(keys.length) //1
console.log(keys[0]) // name

console.log(symbols.length) //1
console.log(symbols[0]) // symbol(name)
ログイン後にコピー
# をインターセプトします。 ##プログラミング関連の知識について詳しくは、プログラミング入門

をご覧ください。 !

以上がES6 のプロキシの詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート