With respect to Reflect’s problem analysis, I recently studied vue3’s response type problem, and encountered Reflect and new Proxy confusion

Making a blog

👇 making blog

Summary of a.

Proxy is used to modify the default behavior of certain operations, which is equivalent to making changes at the language level. Therefore, it is a kind of “meta programming”, that is, programming a programming language.

Proxy can be understood as a layer of “interception” before the target object. All external access to the object must pass this layer of interception. Therefore, Proxy provides a mechanism for filtering and rewriting external access.

Thirteen ways to support Proxy interception operations

  • Get (Target, Key, receiver) Intercepts the reading of object properties
  • Set (Target, Key, value, receiver) Intercepts the setting of object properties
  • From the intercept (target, key)key in proxyReturns a Boolean value.
  • Intercept deleteProperty (target, key)delete proxy[key]Returns a Boolean value.
  • DefineProperty () interceptObject. DefineProperty (proxy, propKey propDesc)Returns a Boolean value
  • Apply (Target, Object, arGS) intercepts Proxy instances as the operation of function calls
  • Constructor (target, args, newRarget) intercepts operations invoked by Proxy instances as constructors
  • SetPrototypeOf (target, prototype) interceptObject.setPrototypeOf(proxy, proto), returns a Boolean value. If the target object is a function, there are two additional operations that can be intercepted.
  • GetPrototypeOf (target)Object.getPrototypeOf(proxy), returns an object.
  • OwnKeys (target)Object.getOwnPropertyNames(proxy),Object.getOwnPropertySymbols(proxy),Object.keys(proxy),for... inLoop to return an array. This method returns the property names of all of the target object’s own properties, andObject.keys()The return result of the object contains only the traversable properties of the target object itself.
  • IsExtensible (target)Object.isExtensible(proxy), returns a Boolean value.
  • PreventExtensible (target)Object.preventExtensions(proxy), returns a Boolean value.
  • Intercept getOwnProrertyDescriptor (target, key)Object.getOwnPropertyDescriptor(proxy, propKey)Returns the description object of the property.

The instance method of Proxy

get()

The get method intercepts a read of a property and can take three parameters, the target object, the property name, and the proxy instance itself (strictly speaking, the object against which the action is directed), the last of which is optional.

var person = {
  name: "Zhang"
};
​
var proxy = new Proxy(person, {
  get: function(target, propKey) {
    if (propKey in target) {
      return target[propKey];
    } else {
      throw new ReferenceError("Prop name "" + propKey + "" does not exist."); }}}); proxy.name// "/"
proxy.age // Throw an error
Copy the code

set()

The set method is used to intercept the assignment of an attribute. It can take four parameters: the target object, the attribute name, the attribute value, and the Proxy instance itself. The last parameter is optional.

const handler = {
    set: function(obj, prop, value, receiver) {
      obj[prop] = value;
      return true; }};const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
console.log(proxy.foo) //bar
Copy the code

apply()

The Apply method intercepts function calls, calls, and apply operations.

The Apply method takes three parameters: the target object, the target object’s context object (this), and the target object’s parameter array.

var handler = {
  apply: function (target, ctx, args) {
    return Reflect.apply(... arguments) *2; }};function sum(left, right) {
  return left + right;
}
var proxy = new Proxy(sum, handler);
proxy(1.2); / / 6
proxy.call(null.5.6); / / 22
proxy.apply(null[7.8]); / / 30
Copy the code

Alternatively, calling reflect. apply directly will also be intercepted.

Reflect.apply(proxy, null[9.10]) / / 38
Copy the code

has()

The has() method is used to intercept the HasProperty operation, which takes effect when determining whether an object has a property. A typical operation is the IN operator.

The has() method can take two parameters, the target object and the name of the property to be queried.

var handler = {
  has (target, key) {
    if (key[0= = ='_') {
      return false;
    }
    return key intarget; }};var target = { _prop: 'foo'.prop: 'foo' };
var proxy = new Proxy(target, handler);
'_prop' in proxy // false
Copy the code

Has () intercepts an error if the original object is not configurable or if extension is disabled.

var obj = { a: 10 };
Object.preventExtensions(obj);
​
var p = new Proxy(obj, {
  has: function(target, prop) {
    return false; }});'a' in p // TypeError is thrown
Copy the code

construct()

The construct() method is used to intercept the new command. Here’s how to write the intercept object.

const handler = {
  construct (target, args, newTarget) {
    return new target(...args);
  }
};
Copy the code

The construct() method takes three arguments.

  • target: Target object.
  • args: Array of constructor arguments.
  • newTarget: When creating instance objects,newThe constructor used by the command (in the following example)p).
const p = new Proxy(function () {}, {
  construct: function(target, args) {
    console.log('called: ' + args.join(', '));
    return { value: args[0] * 10}; }}); (new p(1)).value
// "called: 1"
/ / 10
Copy the code

The construct() method must return an object or an error will be reported.

deleteProperty()

The deleteProperty method intercepts the DELETE operation. If the method throws an error or returns false, the current property cannot be deleted by the delete command.

var handler = {
  deleteProperty (target, key) {
    invariant(key, 'delete');
    delete target[key];
    return true; }};function invariant (key, action) {
  if (key[0= = ='_') {
    throw new Error(`Invalid attempt to ${action} private "${key}" property`); }}var target = { _prop: 'foo' };
var proxy = new Proxy(target, handler);
delete proxy._prop
// Error: Invalid attempt to delete private "_prop" property
Copy the code

defineProperty()

The defineProperty() method intercepts the Object.defineProperty() operation.

var handler = {
  defineProperty (target, key, descriptor) {
    return false; }};var target = {};
var proxy = new Proxy(target, handler);
proxy.foo = 'bar' // Does not take effect
Copy the code

getOwnPropertyDescriptor()

GetOwnPropertyDescriptor intercept () method of the Object. GetOwnPropertyDescriptor (), returns a property description Object, or undefined.

var handler = {
  getOwnPropertyDescriptor (target, key) {
    if (key[0= = ='_') {
      return;
    }
    return Object.getOwnPropertyDescriptor(target, key); }};var target = { _foo: 'bar'.baz: 'tar' };
var proxy = new Proxy(target, handler);
Object.getOwnPropertyDescriptor(proxy, 'wat')
// undefined
Object.getOwnPropertyDescriptor(proxy, '_foo')
// undefined
Object.getOwnPropertyDescriptor(proxy, 'baz')
// { value: 'tar', writable: true, enumerable: true, configurable: true }
Copy the code

The above code, the handler. GetOwnPropertyDescriptor () method for the first character to underline the property name will return undefined.

getPrototypeOf()

The getPrototypeOf() method is used primarily to intercept and retrieve object prototypes. Specifically, intercept the following operations.

  • Object.prototype.__proto__
  • Object.prototype.isPrototypeOf()
  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • instanceof
var proto = {};
var p = new Proxy({}, {
  getPrototypeOf(target) {
    returnproto; }});Object.getPrototypeOf(p) === proto // true
Copy the code

In the code above, the getPrototypeOf() method intercepts Object.getProtoTypeof () and returns a Proto Object.

Note that the return value of the getPrototypeOf() method must be an object or null, otherwise an error is reported. Also, if the target object is non-extensible, the getPrototypeOf() method must return the prototype object of the target object.

isExtensible()

The isExtensible() method intercepts the Object.isextensible () operation.

var p = new Proxy({}, {
  isExtensible: function(target) {
    console.log("called");
    return true; }});Object.isExtensible(p)
// "called"
// true
Copy the code

ownKeys()

The ownKeys() method is used to intercept reads of the object’s own properties. Specifically, intercept the following operations.

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • for... incycle
let target = {
  a: 1.b: 2.c: 3
};
​
let handler = {
  ownKeys(target) {
    return ['a']; }};let proxy = new Proxy(target, handler);
​
Object.keys(proxy)
// [ 'a' ]
Copy the code

preventExtensions()

The preventExtensions() method intercepts object.preventExtensions (). This method must return a Boolean value, otherwise it is automatically converted to a Boolean value.

The limit to this method is that proxy.preventExtensions can only return true if the target Object is not extensible (Object. IsExtensible (proxy) is false), otherwise an error will be reported.

var proxy = new Proxy({}, {
  preventExtensions: function(target) {
    return true; }});Object.preventExtensions(proxy)
// Uncaught TypeError: 'preventExtensions' on proxy: trap returned truish but the proxy target is extensible
Copy the code

setPrototypeOf()

The setPrototypeOf() method is mainly used to intercept object.setPrototypeof () methods.

var handler = { setPrototypeOf (target, proto) { throw new Error('Changing the prototype is forbidden'); }}; var proto = {}; var target = function () {}; var proxy = new Proxy(target, handler); Object.setPrototypeOf(proxy, proto); // Error: Changing the prototype is forbiddenCopy the code

In the above code, an error is reported whenever the target prototype object is modified.

Note that this method can only return a Boolean value, otherwise it is automatically converted to a Boolean value. Also, if the target object is non-extensible, the setPrototypeOf() method cannot change the target object’s prototype.

reference

Nguyen half-stretching