Create a simple Proxy

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
Copy the code

When this instance assigns “proxy” to the proxy.name property, it creates a name on the target. The proxy simply forwards the operation to the target, which does not store the property. Proxy. name and target.name refer to target.name.

Use set traps to validate properties

The set trap accepts four parameters:

1. TrapTarget: The object used to receive attributes (the target of the proxy)

2. Key: Attribute key (string or symbol) to be written

3. Value: indicates the attribute value to be written

4.receiver: The object (usually the agent) on which the operation takes place

let target = {
    name: "target"
}

let proxy = new Proxy(target, {
    set(trapTarget, key, value, receiver) {
        if(! trapTarget.hasOwnProperty(key)) {if (isNaN(value)) {
                throw new TypeError("Attribute must be a number")}}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" // There is an error because there are no numbers
Copy the code

This instance starts the set function every time it changes the value of the proxy outside.

Validate object structures with get traps

Get receives three parameters

1. TrapTarget: The object used to receive attributes (the target of the proxy)

2. Key: Attribute key (string or symbol) to be written

3. Receiver: The object (usually the agent) on which the operation takes place

let proxy = new Proxy({}, {
    get(trapTarget, key, receiver) {
        if(! (keyin receiver)) {
            throw new TypeError("Properties" + key + "Doesn't exist.")}return Reflect.get(trapTarget, key, receiver)
    }
})

proxy.name = "proxy"

console.log(proxy.name) //proxy

console.log(proxy.age) // An error will be thrown if the attribute does not exist
Copy the code

The GET method is triggered when we access the object properties created by the proxy

Use the HAS trap so there are attributes

Has accepts two parameters:

1. TrapTarget: The object used to receive attributes (the target of the proxy)

2. Key: Attribute key (string or symbol) to be written

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
Copy the code

We start the has function whenever we determine whether or not the proxy has attributes

Use the deleteProperty trap to prevent properties from being deleted

DeleteProperty accepts two arguments:

1. TrapTarget: The object used to receive attributes (the target of the proxy)

2. Key: Attribute key (string or symbol) to be written

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
Copy the code

The deleteProperty function is triggered when an external proxy property is deleted

Prototype trap agent (setProptotypeOf getPrototypeOf)

SetProptotypeOf takes two arguments

1. TrapTarget: The object used to receive attributes (the target of the proxy)

2. Proto: Objects used as prototypes

let target = {}

let proxy = new Proxy(target, {

    // called when accessing
    getPrototypeOf(trapTarget) {
        return null
    },
    // called when changing
    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, {}) / / success

Object.setPrototypeOf(proxy, {}) // Throw an error

Copy the code

If it works

let target = {}

let proxy = new Proxy(target, {

    // called when accessing
    getPrototypeOf(trapTarget) {
        return Reflect.getPrototypeOf(trapTarget)
    },
    // called when changing
    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, {}) / / success

Object.setPrototypeOf(proxy, {}) / / success
Copy the code

Property descriptor trap

DefineProperty accepts three arguments:

1. TrapTarget: The object used to receive attributes (the target of the proxy)

2. Key: Attribute key (string or symbol) to be written

3. Descriptor: Description object of attributes

let proxy = new Proxy({}, {
    defineProperty(trapTarget, key, descriptor) { // Descriptor can only accept enumerable, 64x, value, writeable, get, and 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"
})
Copy the code

In the external call defineProperty | getOwnPropertyDescriptor triggered when internal definenProperty | getOwnPropertyDescriptor method.

OwnKeys trap

OwnKeys trap can intercept the external Object. The keys (), Object, getOwnPropertyName (), Object, getOwnPropertySymbols () and the Object. The assign () four methods

let proxy = new Proxy({}, {
    ownKeys(trapTarget) {
        return Reflect.ownKeys(trapTarget).filter(key= > {
            return typeofkey ! = ="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)
Copy the code