This is the first day of my participation in the August Text Challenge.More challenges in August
Recently, because of a chance coincidence, discovered this early heard of JS native objects, so deliberately spent time to understand.
introduce
First, a Proxy is a Proxy that creates a specified object to intercept or redefine basic operations against that object. The usage is as follows:
const proxy = new Proxy(target, handler)
Copy the code
Proxy is a proxy. Target is an object that needs to be proxied; Handler is an object that contains a set of functions that define the logic of the agent’s behavior.
The Target object
A target is an object type. It can be a normal object (or even an empty object), an array, a function, and so on.
Handler Handler function
Before we begin, it is important to note that none of these handlers need to be implemented, and those that are not will remain the default.
Let’s start with the two most commonly used ones: handler.get() and handler.set(). This literally hijacks the get and set operations on proxy properties.
var foo = {
b: 'lol'
}
var handler = {
set(obj, prop, val) {
console.log(`set foo.${prop} = ${val}`)
if (/^p\_/.test(prop) || (prop in obj)) {
obj[prop] = val
} else {
console.log(`failed to set prop '${prop}' to object 'foo'`)}},get(obj, prop) {
console.log(`get foo.${prop}`)
if (prop in obj) {
return obj[prop]
} else {
console.log(`prop '${prop}' is undefined in 'foo' and illegal to read`)}}}var proxy = new Proxy(foo, handler);
proxy.a = 1
// output: set foo.a = 1
// output: failed to set prop 'a' to object 'foo'
proxy.b = 'Zzz'
// output: set foo.b = Zzz
proxy.p_a = 100
// output: set foo.p_a = 100
foo.p_a = 200
console.log(proxy.p_a)
// output: get foo.p_a
console.log(foo.a, foo.b, foo.p_a)
// output: undefined "Zzz" 200
console.log(proxy.c)
// output: get foo.c
// output: prop 'c' is undefined in 'foo' and illegal to read
Copy the code
Something that is used less often:
handler.apply(func, thisArg, argumentsList)
Hijacking functions to perform operations
// Code examples
function sum(a, b) {
return a + b
}
const handler = {
apply: function(func, thisArg, argumentsList) {
console.log(`sum: ${argumentsList}`)
let sum = 0
for (let i = 0; i < argumentsList.length; i++) {
sum = func(sum, argumentsList[i])
}
return sum
}
}
const proxy = new Proxy(sum, handler)
console.log(sum(1.2))
// output: 3
console.log(proxy(1.2.3.10))
// output: 16
Copy the code
handler.construct(func, argumentsList)
Hijack the execution of the new operator
function Person(a, b) {
this.name = a
this.age = b
}
const handler = {
id_count: 12340.construct: function(func, argumentsList) {
console.log(`args: ${argumentsList}`)
const ppl = newfunc(... argumentsList) ppl.id =this.id_count++
return ppl
}
}
const proxy = new Proxy(Person, handler)
console.log(new Person('Jack'.2))
// output: {name: "Jack", age: 2}
console.log(new proxy('Ben'.10))
// output: {name: "Ben", age: 10, id: 12340}
console.log(new proxy('David'.8))
// output: {name: "David", age: 8, id: 12341}
Copy the code
handler.defineProperty(obj, prop, descriptor)
Hijack the attribute assignment operation
// Code examples
var foo = {
b: 'lol'
}
var handler = {
defineProperty(obj, prop, descriptor) {
console.log(`define foo.${prop} = ${descriptor.value}`)
obj[prop] = descriptor.value
return true}}var proxy = new Proxy(foo, handler);
proxy.a = 1
// output: define foo.a = 1
proxy.b = 'Zzz'
// output: define foo.b = Zzz
Object.defineProperty(proxy, 'num', {
value: Awesome!
})
// output: define foo.num = 666
Copy the code
handler.deleteProperty(obj, prop)
Hijack the operation of the delete operator
// Code examples
var foo = {
b: 'lol'
}
var handler = {
deleteProperty(obj, prop) {
console.log(`delete foo.${prop}`)
delete foo[prop]
return true}}var proxy = new Proxy(foo, handler);
delete proxy.b
// output: delete foo.b
console.log(foo)
// output: {}
Copy the code
handler.getOwnPropertyDescriptor(obj, prop)
The implementation of hijacked Object. GetOwnPropertyDescriptor () method
// Code examples
var foo = {
b: 'lol'
}
var handler = {
getOwnPropertyDescriptor(obj, prop) {
console.log(`getProp foo.${prop}`)
if (prop in obj) {
return Object.getOwnPropertyDescriptor(obj, prop)
} else {
return { configurable: true.enumerable: false.value: ' '}}}}var proxy = new Proxy(foo, handler);
console.log(Object.getOwnPropertyDescriptor(proxy, 'a'))
// output: getProp foo.a
// output: {value: "", writable: false, enumerable: false, configurable: true}
console.log(Object.getOwnPropertyDescriptor(proxy, 'b'))
// output: getProp foo.b
// output: {value: "lol", writable: true, enumerable: true, configurable: true}
Copy the code
handler.getPrototypeOf(obj)
Hijack the execution of the Object.getPrototypeof () method
// Code examples
var foo = {
b: 'lol'
}
var fooProto = {
b: 'Zzz'
}
var handler = {
getPrototypeOf(obj) {
console.log(`getProto foo`)
return fooProto
}
}
var proxy = new Proxy(foo, handler);
console.log(Object.getPrototypeOf(proxy))
// output: getProto foo
// output: {b: "Zzz"}
Copy the code
handler.setPrototypeOf(obj, proto)
Hijack the execution of the object.setPrototypeof () method
// Code examples
var foo = {
}
var fooProto = {
b: 'Zzz'
}
var handler = {
setPrototypeOf(obj, proto) {
console.log(`setProto foo`)
Object.setPrototypeOf(obj, proto)
obj.hasProto = true
return true}}var proxy = new Proxy(foo, handler);
Object.setPrototypeOf(proxy, fooProto)
// output: setProto foo
console.log(foo)
// output: {hasProto: true}
console.log(foo.b)
// output: "Zzz"
Copy the code
handler.has(obj, prop)
Hijack the execution of the IN operator
// Code examples
var foo = {
__a: 1.b: 'lol'
}
var handler = {
has(obj, prop) {
console.log(`has foo.${prop}`)
if (/ / ^ __.test(prop)) {
return false;
} else {
return prop in obj
}
}
}
var proxy = new Proxy(foo, handler);
console.log('__a' in proxy)
// output: has foo.__a
// output: false
console.log('b' in proxy)
// output: has foo.b
// output: true
console.log('c' in proxy)
// output: has foo.c
// output: false
Copy the code
Handler. IsExtensible (obj) and handler. PreventExtensions (obj)
Hijack the execution of the Object.isextensible () and Object.preventExtensions() methods
// Code examples
var foo = {
canExtend: true.b: 'lol'
}
var handler = {
isExtensible(obj) {
console.log(`isExtensible foo`)
return Object.isExtensible(obj)
},
preventExtensions(obj) {
console.log(`preventExtensions foo`)
obj.canExtend = false
return Object.preventExtensions(obj)
}
}
var proxy = new Proxy(foo, handler);
console.log(Object.isExtensible(proxy))
// output: isExtensible foo
// output: true
console.log(proxy.canExtend)
// output: true
Object.preventExtensions(proxy)
// output: preventExtensions foo
console.log(Object.isExtensible(proxy))
// output: isExtensible foo
// output: false
console.log(proxy.canExtend)
// output: false
Copy the code
practice
As you can see from the above, Proxy objects can do a lot of things that were previously unimaginable.
Restriction-check
Encapsulate and hide the target object, monitor and restrict the operation behavior, and verify the property processing to determine whether the operation, assignment data and type are valid.
For example, the Qiankun micro front end framework uses Proxy to build JS sandbox
expand
Do additional extensions to the original target object, such as building an object with more initial data and methods, giving more power to method calls, and so on.