>  기사  >  웹 프론트엔드  >  ES6의 프록시에 대한 심층 분석

ES6의 프록시에 대한 심층 분석

青灯夜游
青灯夜游앞으로
2021-07-05 11:23:251621검색

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"를 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" // 这里会报错因为不数字

이 인스턴스는 값이 바뀔 때마다 설정 함수를 트리거합니다. 프록시가 외부에서 변경되었습니다.

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 메서드가 트리거됩니다.

사용에는 트랩이 있으므로 이미 속성이 있습니다.

has가 수신합니다. 2개의 매개변수:

1.trapTarget: 속성을 받는 데 사용되는 개체(에이전트의 대상)

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

deleteProperty는 프록시 속성이 실행될 때 트리거됩니다. 함수

Prototype 프록시 트랩(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, {}) // 成功

속성 설명자 트랩

defineProperty는 세 가지 매개변수를 받습니다.

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가 외부에서 호출될 때 트리거됩니다.

ownKeys 트랩

ownKeys 트랩은 네 가지 외부 메소드인 Object.keys(), Object.getOwnPropertyName(), Object.getOwnPropertySymbols() 및 Object.sign()

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제