当前位置: 首页 > news >正文

【js】Proxy学习笔记

这篇文章可以说是MDN Proxy文档的精简版,把所有核心知识点都浓缩提炼出来了。😁😁😁凑不要脸的自夸一下,可能仍有不足,但我加上MDN的链接了。如果表述或者代码有不对的地方,欢迎指正。

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。只能通过 new 关键字来调用,如果不使用 new 关键字调用,则会抛出 TypeError 错误。

语法

const p = new Proxy(target, handler)

参数解释:

  • target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  • handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
  • 示例:
    proxyExample() {const obj = {name: 'kk',age: 18}const proxyObj = new Proxy(obj, {get(target, key) {return target[key] || `属性不存在`},set(target, key, value) {target[key] = valuereturn true // 返回 true 表示设置成功}})console.log(proxyObj.name) // 输出: kkconsole.log(proxyObj.age) // 输出: 18proxyObj.age = 20 // 设置属性console.log(proxyObj.age) // 输出: 20
    },
    

方法

  • Proxy.revocable():创建一个可撤销的Proxy对象。
    proxyRevocableExample() {const obj = { name: 'll', age: 18 }const revocable = Proxy.revocable(obj, {get(target, key) {return target[key] || `属性不存在`},set(target, key, value) {target[key] = valuereturn true // 返回 true 表示设置成功}})console.log(revocable) // 输出: {proxy: Proxy(Object), revoke: ƒ}// 注意使用revocable.proxy设置属性console.log(revocable.proxy.name) // 输出: llrevocable.proxy.name = 'ii' // 设置属性console.log(revocable.proxy.name) // 输出: iirevocable.revoke() // 撤销代理console.log(revocable.proxy.name) // 输出报错,因为代理已被撤销,[vue warn]: Error in mounted hook: "TypeError: Cannot perform 'get' on a proxy that has been revoked"
    }
    

console.log(revocable) // 输出: {proxy: Proxy(Object), revoke: ƒ}

  • proxy:表示新生成的代理对象本身,和用一般方式 new Proxy(target, handler) 创建的代理对象没什么不同,只是它可以被撤销掉。
  • **revoke:**撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。一旦某个代理对象被撤销,它将变得几乎完全不可调用,在它身上执行任何的可代理操作都会抛出 TypeError 异常(注意,可代理操作一共有 14 种,执行这 14 种操作以外的操作不会抛出异常)。一旦被撤销,这个代理对象便不可能被直接恢复到原来的状态,同时和它关联的目标对象以及处理器对象都有可能被垃圾回收掉。再次调用撤销方法 revoke() 则不会有任何效果,但也不会报错。

handler 对象的方法

handler对象 是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap:处理器函数有时候也被称为劫持(trap),这是由于它们会对底层被代理对象的调用进行劫持),它们都是可选的。开发者可以按需覆盖,如果没有被重新定义,仍会按原始对象的默认方式工作,不会报错,也不会被拦截。

handler.getPrototypeOf():

Object.getPrototypeOf 方法的捕捉器。

proxyTrapGetPrototypeOf() {const monster1 = {eyeCount: 4}const monsterPrototype = {eyeCount: 2}const proxy1 = new Proxy(monster1, {getPrototypeOf(target) {// 这里直接返回自定义的原型对象return monsterPrototype //替换了目标对象的真实原型}})console.log(Object.getPrototypeOf(proxy1) === monsterPrototype)// 输出: trueconsole.log(Object.getPrototypeOf(proxy1).eyeCount)// 输出: 2
}

5 种触发 getPrototypeOf 代理方法的方式:

  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • Object.prototype.proto
  • Object.prototype.isPrototypeOf()
  • instanceof
    proxyTrapGetPrototypeOf2() {var p = new Proxy({},{getPrototypeOf(target) {return Array.prototype}})console.log(Object.getPrototypeOf(p) === Array.prototype) // 输出: trueconsole.log(Reflect.getPrototypeOf(p) === Array.prototype) // 输出: trueconsole.log(p.__proto__ === Array.prototype) // 输出: trueconsole.log(Array.prototype.isPrototypeOf(p)) // 输出: trueconsole.log(p instanceof Array) // 输出: true
    }
    

如果违背了以下的约束,proxy 会抛出 TypeError:

  • getPrototypeOf() 方法返回的不是对象也不是 null。
  • 目标对象是不可扩展的,且 getPrototypeOf() 方法返回的原型不是目标对象本身的原型。
    var obj = Object.preventExtensions({})
    var p = new Proxy(obj, {getPrototypeOf(target) {return {}}
    })
    Object.getPrototypeOf(p)
    //报错:TypeError: 'getPrototypeOf' on proxy: proxy target is non-extensible but the trap did not return its actual prototype
    

handler.setPrototypeOf():

Object.setPrototypeOf 方法的捕捉器。

proxyTrapSetPrototypeOf() {const proxyObj = new Proxy({},{setPrototypeOf(target, proto) {console.log(`Setting prototype to:`, proto)return Reflect.setPrototypeOf(target, proto) // 设置原型}})Object.setPrototypeOf(proxyObj, Array.prototype) // 设置原型为 Array.prototypeconsole.log(Object.getPrototypeOf(proxyObj) === Array.prototype) // 输出: true
}

该方法会拦截目标对象的以下操作:

  • Object.setPrototypeOf()
  • Reflect.setPrototypeOf()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果 target不可扩展,原型参数必须与Object.getPrototypeOf(target)值相同。

handler.isExtensible():

Object.isExtensible 方法的捕捉器。

proxyTrapIsExtensible() {const proxyObj = new Proxy({}, {isExtensible(target) {return Reflect.isExtensible(target) // 返回目标对象的可扩展性},preventExtensions(target) {console.log('Preventing extensions on target')return Reflect.preventExtensions(target) // 阻止扩展}})console.log(Object.isExtensible(proxyObj)) // 输出: trueObject.preventExtensions(proxyObj) // 阻止扩展console.log(Object.isExtensible(proxyObj)) // 输出: false
}

该方法会拦截目标对象的以下操作:

  • Object.isExtensible()
  • Reflect.isExtensible()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • Object.isExtensible(proxy) 必须同 Object.isExtensible(target) 返回相同值,即当目标对象可扩展时,isExtensible 必须返回 true;当目标对象不可扩展时,isExtensible 陷阱必须返回 false。
    var p = new Proxy({},{isExtensible: function (target) {return false // return 0; return NaN 等都会报错}
    })
    Object.isExtensible(p)
    //输出报错:TypeError: 'isExtensible' on proxy: trap result does not reflect extensibility of proxy target (which is 'true')
    

handler.preventExtensions():

Object.preventExtensions 方法的捕捉器。

proxyTrapPreventExtensions() {const target = {isExtensible: true}const proxyObj = new Proxy(target, {preventExtensions(target) {target.isExtensible = falseObject.preventExtensions(target)return true}})console.log(target.isExtensible) // 输出: trueObject.preventExtensions(proxyObj) // 阻止扩展console.log(target.isExtensible) // 输出: falseconsole.log(Object.isExtensible(proxyObj)) // 输出: falseconsole.log(Object.isExtensible(target)) // 输出: false
}

该方法会拦截目标对象的以下操作:

  • Object.preventExtensions()
  • Reflect.preventExtensions()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果目标对象是可扩展的,那么只能返回 false
    var p = new Proxy({},{preventExtensions: function (target) {return true}}
    )
    Object.preventExtensions(p)
    // 输出报错:TypeError: 'preventExtensions' on proxy: trap returned truish but the proxy target is extensible
    

handler.getOwnPropertyDescriptor():

Object.getOwnPropertyDescriptor 方法的捕捉器。

proxyTrapGetOwnPropertyDescriptor() {const proxyObj = new Proxy({name: 'kk',age: 18},{getOwnPropertyDescriptor: (target, key) =>Reflect.getOwnPropertyDescriptor(target, key)})console.log(Object.getOwnPropertyDescriptor(proxyObj, 'name'))// 输出: { value: 'kk', writable: true, enumerable: true, configurable: true }
}

该方法会拦截目标对象的以下操作:

  • Object.getOwnPropertyDescriptor()
  • Reflect.getOwnPropertyDescriptor()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • getOwnPropertyDescriptor 必须返回一个 object 或 undefined。
  • 如果属性作为目标对象的不可配置的属性存在,则该属性无法报告为不存在。
    • 含义: 目标对象身上真的有一个 configurable: false 的属性 x,你就不能在 getOwnPropertyDescriptor() 里返回 undefined(假装没有)。
    • 示例:
      const target = {};
      Object.defineProperty(target, 'x', { value: 1, configurable: false });const proxy = new Proxy(target, {getOwnPropertyDescriptor(t, prop) {if (prop === 'x') return undefined; // ❌ 撒谎}
      });Object.getOwnPropertyDescriptor(proxy, 'x'); 
      // 输出报错:TypeError: 'getOwnPropertyDescriptor' on proxy: trap returned undefined for property 'x' which is non-configurable in the proxy target
      
  • 如果属性作为目标对象的属性存在,并且目标对象不可扩展,则该属性无法报告为不存在。
    • 含义: 一旦目标被 Object.preventExtensions() 锁定,所有已经存在的自有属性都必须能被查到;返回 undefined 就报错。
    • 示例:
      const target = { y: 2 };
      Object.preventExtensions(target);const proxy = new Proxy(target, {getOwnPropertyDescriptor(t, prop) {if (prop === 'y') return undefined; // ❌ 撒谎}
      });Object.getOwnPropertyDescriptor(proxy, 'y');
      // 输出报错:TypeError: 'getOwnPropertyDescriptor' on proxy: trap returned undefined for property 'y' which exists in the non-extensible proxy target
      
  • 如果属性不存在作为目标对象的属性,并且目标对象不可扩展,则不能将其报告为存在。
    • 含义: 目标被冻结后,代理就不能再“伪造”一个原本不存在的属性;否则抛异常。
    • 示例:
      const target = {};
      Object.preventExtensions(target);
      const proxy = new Proxy(target, {getOwnPropertyDescriptor(t, prop) {if (prop === 'z') return { value: 99, configurable: true }; // ❌ 伪造}
      });
      Object.getOwnPropertyDescriptor(proxy, 'z'); 
      // 输出报错:TypeError: 'getOwnPropertyDescriptor' on proxy: trap returned descriptor for property 'z' that is incompatible with the existing property in the proxy target
      
  • 属性不能被报告为不可配置,如果它不作为目标对象的自身属性存在,或者作为目标对象的可配置的属性存在。
    • 含义: 你返回的描述符里 { configurable: false } 必须“有根有据”,只有目标对象里真的有一个对应且原本就是 configurable: false 的属性时,你才能这么写。否则属于“伪造不可配置”,抛错。
    • 示例(伪造不可配置):
      const target = { w: 3 }; // w 默认 configurable: true
      const proxy = new Proxy(target, {getOwnPropertyDescriptor(t, prop) {if (prop === 'w') return { value: 3, configurable: false }; // ❌ 撒谎}
      });Object.getOwnPropertyDescriptor(proxy, 'w'); 
      // 输出报错:peError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for property 'w' which is either non-existent or configurable in the proxy target
      
  • Object.getOwnPropertyDescriptor(target)的结果可以使用 Object.defineProperty 应用于目标对象,也不会抛出异常。
    • 含义:
      你返回的描述符必须是合法且完整的:
      • 如果返回了存取器描述符 { get: …, set: … },这两个函数必须真正可调用;
      • 如果返回了数据描述符 { value, writable, … },这些字段必须能被 defineProperty 接受。
        否则同样抛 TypeError。
    • 示例:
      const target = {};
      const proxy = new Proxy(target, {getOwnPropertyDescriptor(t, prop) {// ❌ 返回了一个不可用的 getter:不是函数if (prop === 'bad') {return { get: 123, enumerable: true, configurable: true };}}
      });Object.getOwnPropertyDescriptor(proxy, 'bad');
      // 输出报错:TypeError: Getter must be a function: 123
      

handler.defineProperty():

Object.defineProperty 方法的捕捉器。
默认情况下,使用 Object.defineProperty() 添加的属性是不可写、不可枚举和不可配置的。

proxyTrapDefineProperty() {var p = new Proxy({},{defineProperty(target, prop, descriptor) {console.log(descriptor) //输出:{value: 'proxy'}return Reflect.defineProperty(target, prop, descriptor)}})Object.defineProperty(p, 'name', {value: 'proxy',type: 'custom'})console.log(p.name) // 输出:proxyconsole.log(Object.getOwnPropertyDescriptor(p, 'name')) //输出:{value: 'proxy', writable: false, enumerable: false, configurable: false}console.log(p) // 输出:Proxy(Object) {name: 'proxy'}
}

当调用 Object.defineProperty() 或者 Reflect.defineProperty(),传递给 defineProperty 的 descriptor 有一个限制 - 只有以下属性才有用,非标准的属性将会被无视:

  • enumerable
  • configurable
  • writable
  • value
  • get
  • set

该方法会拦截目标对象的以下操作:

  • Object.defineProperty()
  • Reflect.defineProperty()
  • proxy.property=‘value’

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果目标对象不可扩展,将不能添加属性。
  • 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话。
  • 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的。
  • 如果一个属性在目标对象中存在对应的属性,那么 Object.defineProperty(target, prop, descriptor) 将不会抛出异常。
  • 在严格模式下,false 作为 handler.defineProperty 方法的返回值的话将会抛出 TypeError 异常。

handler.has():

in 操作符的捕捉器。

proxyTrapHas() {const proxyObj = new Proxy({ name: 'kk', age: undefined, height: null },{has(target, key) {return key in target // 返回 true 或 false}})console.log('name' in proxyObj) // 输出: trueconsole.log('age' in proxyObj) // 输出: trueconsole.log('height' in proxyObj) // 输出: trueconsole.log('weight' in proxyObj) // 输出: false
}

该方法会拦截目标对象的以下操作:

  • 属性查询:foo in proxy
  • 继承属性查询:foo in Object.create(proxy)
  • with 检查: with(proxy) { (foo); }
    function proxyTrapHas2() {const proxyObj = new Proxy({ name: 'kk' },{has(target, key) {return key in target // 返回 true 或 false}})with (proxyObj) {console.log('name' in proxyObj) // 输出: trueconsole.log('age' in proxyObj) // 输出: false}
    }
    
  • Reflect.has()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏。
  • 如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏。
    var obj = { a: 10 }
    Object.preventExtensions(obj)
    var p = new Proxy(obj, {has: function (target, prop) {return false}
    })
    'a' in p
    // 输出报错:TypeError: 'has' on proxy: trap returned falsish for property 'a' but the proxy target is not extensible
    

handler.get():

属性读取操作的捕捉器。

proxyTrapGet() {const proxyObj = new Proxy({ a: 10 },{get(target, key) {console.log(`Accessing property: ${key}`)return target[key] || `属性不存在`}})console.log(proxyObj.a) // 输出: 10console.log(proxyObj.b) // 输出: 属性不存在
}

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果要访问的目标属性是不可写且不可配置的,则返回的值必须与该目标属性的值相同。
    proxyTrapGet() {const obj = {}Object.defineProperty(obj, 'a', {configurable: false,enumerable: false,writable: false,value: '1'})const proxyObj = new Proxy(obj, {get(target, key) {console.log(`Accessing property: ${key}`) // 输出: Accessing property: age, name1return 101}})console.log(proxyObj.a)// 输出报错: mounted hook: "TypeError: 'get' on proxy: property 'a' is a read-only and non-configurable data property on the proxy target but the proxy did not return its actual value (expected '1' but got '101')"
    }
    
  • 如果要访问的目标属性没有配置访问方法,即 get 方法是 undefined 的,则返回值必须为 undefined。
    const target = {}
    Object.defineProperty(target, 'secret', {set(v) {},get: undefined, // 没有 getter → [[Get]] 为 undefinedconfigurable: false //必须为 false,否则不会抛出错误,直接返回proxy get设置的值
    })
    const proxy = new Proxy(target, {get(t, prop, receiver) {return 'fake-value' // 返回一个假的值}
    })
    console.log(proxy.secret)
    // 输出报错: TypeError: 'get' on proxy: property 'secret' is a non-configurable accessor property on the proxy target and does not have a getter function, but the trap did not return 'undefined' (got 'fake-value')   
    

handler.set():

属性设置操作的捕捉器。

proxyTrapSet() {const proxy1 = new Proxy({ eyeCount: 4 },{set(target, prop, value, receiver) {if (prop === 'eyeCount' && value % 2 !== 0) {console.log('Monsters must have an even number of eyes')return true // 重要,必须返回布尔值,表示设置是否成功} else {return Reflect.set(target, prop, value, receiver)}}})proxy1.eyeCount = 1console.log(proxy1.eyeCount) //输出:4proxy1.eyeCount = 2console.log(proxy1.eyeCount) //输出:2
}

set() 方法应当返回一个布尔值

  • 返回 true 代表属性设置成功。
  • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常。

该方法会拦截目标对象的以下操作:

  • 指定属性值:proxy[foo] = bar 和 proxy.foo = bar
  • 指定继承者的属性值:Object.create(proxy)[foo] = bar
  • Reflect.set()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 若目标属性是一个不可写且不可配置的数据属性,则不能改变它的值。
    const target = {}
    Object.defineProperty(target, 'id', {value: 42,writable: false,configurable: false // 永久只读
    })
    const proxy = new Proxy(target, {set(t, prop, val) {// 无论返回 false 还是强行 Reflect.set// 引擎都会检测到冲突并抛 TypeErrorreturn Reflect.set(t, prop, val) // 这里会返回 false}
    })
    proxy.id = 99
    // 输出报错: TypeError: 'set' on proxy: trap returned falsish for property 'id'
    
  • 如果目标属性没有配置存储方法,即 [[Set]] 属性的是 undefined,则不能设置它的值。
const target = {_name: 'Tom'
}
// 仅定义 getter,没有 setter
Object.defineProperty(target, 'name', {get() {return this._name},set: undefined // 显式声明无 setter
})
const proxy = new Proxy(target, {set(t, prop, val) {return Reflect.set(t, prop, val) // 会返回 false}
})
proxy.name = 'Jerry'
// 输出报错: TypeError: 'set' on proxy: trap returned falsish for property 'name'
  • 在严格模式下,如果 set() 方法返回 false,那么也会抛出一个 TypeError 异常。

handler.deleteProperty():

delete 操作符的捕捉器。

proxyTrapDeleteProperty() {const proxyObj = new Proxy({ name: 'kk', age: 18 },{deleteProperty(target, key) {console.log(`Deleting property: ${key}`) // 输出: Deleting property: age, name1return Reflect.deleteProperty(target, key)}})delete proxyObj.age // 删除 age 属性console.log(proxyObj) // 输出: { name: 'kk' }delete proxyObj.name1 // 删除 name1 属性
}

在JavaScript中,delete操作符具有以下特性:当尝试删除不存在的属性时,不会抛出错误,而是会静默返回true。所以执行到删除name1属性时没有报错。
delete删除对象不存在属性
该方法会拦截目标对象的以下操作:

  • 删除属性:delete proxy[foo]和delete proxy.foo
  • Reflect.deleteProperty()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果目标对象的属性是不可配置的,那么该属性不能被删除。

handler.ownKeys():

Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。

proxyTrapOwnKeys() {const monster1 = {_age: 111,[Symbol('secret')]: 'I am scared!',eyeCount: 4}const handler1 = {ownKeys(target) {return Reflect.ownKeys(target)}}const proxy1 = new Proxy(monster1, handler1)for (const key of Object.keys(proxy1)) {console.log('Object.keys:*******', key) // 输出: _age eyeCount}for (const key of Object.getOwnPropertyNames(proxy1)) {console.log('Object.getOwnPropertyNames:-----', key) // 输出: _age eyeCount}for (const key of Object.getOwnPropertySymbols(proxy1)) {console.log('Object.getOwnPropertySymbols:++++++', key.toString()) // 输出: Symbol(secret)}for (const key in proxy1) {console.log('for...in:******', key.toString()) // 输出: Symbol(secret)}for (const key of Reflect.ownKeys(proxy1)) {console.log('Reflect.ownKeys:-----', key) // 现在会输出: _age, eyeCount, Symbol(secret)}
}

proxyTrapOwnKeys输出
该方法会拦截目标对象的以下操作:

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • Reflect.ownKeys()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • ownKeys 的结果必须是一个数组。
  • 数组的元素类型要么是一个 String ,要么是一个 Symbol。
    proxyTrapOwnKeys2() {var p = new Proxy({},{ownKeys: function (target) {// 下面的返回类型都会报错return [123, 12.5, true, false, undefined, null, {}, []]}})console.log(Object.getOwnPropertyNames(p))//输出报错:TypeError: 123 is not a valid property name
    }
    
  • 结果列表必须包含目标对象的所有不可配置(non-configurable)、自有(own)属性的 key.
    • 含义: 如果目标对象上有一个属性 x,且它的描述符是 { configurable: false },那么你在 ownKeys() 返回的数组里必须包含 “x”。
    • 目的: 防止代理对象“隐藏”目标对象上不可删除的属性,破坏语言一致性。
    • 示例:
      const target = {};
      Object.defineProperty(target, 'x', { value: 1, configurable: false });
      const proxy = new Proxy(target, {ownKeys() {return []; // ❌ 漏了不可配置的 'x',会抛 TypeError}
      });
      Object.keys(proxy); 
      // 输出报错:TypeError: 'ownKeys' on proxy: trap result did not include 'x'
      
  • 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的 key,不能有其他值。
    • 含义: 如果目标对象被 Object.preventExtensions(target) 锁定,不能再添加新属性,那么 ownKeys() 返回的数组必须恰好等于目标对象当前的全部自有属性 key——既不能多也不能少。
    • 目的: 保证不可扩展对象的行为一致性,防止代理“伪造”或“隐藏”属性。
    • 示例:
      const target = { a: 1 };
      Object.preventExtensions(target);
      const proxy = new Proxy(target, {ownKeys() {return ['a', 'b']; // ❌ 多了 'b',会抛 TypeError}
      });
      Object.keys(proxy); 
      // 输出报错:TypeError: 'ownKeys' on proxy: trap returned extra keys but proxy target is non-extensible
      

handler.apply():

函数调用操作的捕捉器。

proxyTrapApply() {function sum(a, b) {return a + b}const sumProxy = new Proxy(sum, {/** thisArg:被调用时的上下文对象。* args:被调用时的参数数组。*/apply(target, thisArg, args) {console.log(`Applying sum function with args: ${args}`,`thisArg:`,thisArg)// 输出: Applying sum function with args: 1,2 thisArg: undefinedreturn target.apply(thisArg, args) // 调用原函数}})console.log(sumProxy(1, 2)) // 输出: 3
}

该方法会拦截目标对象的以下操作:

  • proxy(…args)
  • Function.prototype.apply()和Function.prototype.call()
  • Reflect.apply()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • target必须是可被调用的。 而且,它必须是一个函数对象。

handler.construct():

new 操作符的捕捉器,必须返回一个对象,否则代理将会抛出 TypeError错误。

proxyTrapNew() {function Person(name, age) {this.name = namethis.age = age}const personProxy = new Proxy(Person, {construct(target, args, newTarget) {console.log(`Creating a new person with name: ${args[0]} and age: ${args[1]}`,`newTarget:`,newTarget)// 输出: Creating a new person with name: John and age: 30 newTarget: Proxy(Function) {length: 2, name: 'Person', prototype: {…}}return new target(...args)}})const person = new personProxy('John', 30)console.log(person) // 输出: Person { name: 'John', age: 30 }
}

该方法会拦截目标对象的以下操作:

  • new proxy(…args)
  • Reflect.construct()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 必须返回一个对象。
    var p = new Proxy(function () {}, {construct: function (target, argumentsList, newTarget) {return 1}
    })
    new p()
    // 输出报错: TypeError:'construct' on proxy: trap returned non-object ('1')
    
  • 代理初始化时,传给它的target必须具有一个有效的构造函数供new操作符调用。
    var p = new Proxy({},{construct: function (target, argumentsList, newTarget) {return {}}}
    )
    new p()
    // 输出报错: TypeError: p is not a constructor
    

参考

  • MDN Proxy
http://www.xdnf.cn/news/1181845.html

相关文章:

  • k8s常用基础命令总结
  • 电科金仓新一代数据库一体机:AI赋能,三骏守护,引领国产数据库智能变革
  • 【LeetCode 热题 100】22. 括号生成——(解法一)选左括号还是选有括号
  • 基于粒子群优化的PID控制在药液流量控制系统中的应用
  • Python常用医疗AI库以及案例解析(场景化进阶版)
  • SqlRest让SQL秒变Http API,还支持20+数据库(含国产数据库)
  • 100条常用SQL语句大全
  • C++20协程异步
  • 论文Review Registration TEASER | TRO | MIT出品,点云配准经典BenchMark | 硬核的数学长文
  • 蜘蛛强引的原理与百度SEO的关系
  • Qt(资源库和按钮组)
  • SpringBoot+AI+Web3实战指南
  • pytest官方Tutorial所有示例详解(一)
  • 洛谷刷题7.24
  • 优选算法:移动零
  • 计算机网络知识点总结 (2)
  • go语言基础教程:1. Go 下载安装和设置
  • Java网络编程入门:从基础原理到实践(二)
  • 算法第三十八天:动态规划part06(第九章)
  • uboot FPGA调试环境搭建
  • io_uring:Linux异步I/O的革命性突破
  • 星慈光编程虫2号小车讲解第四篇--触摸按键
  • 平时遇到的错误码及场景?404?400?502?都是什么场景下什么含义,该怎么做 ?
  • vue3核心语法
  • (进阶向)Python第十四期OpenCv图像预处理方法[2]
  • 跨境支付入门~国际支付结算(稳定币)
  • 深度分析Java多线程机制
  • AI实践:Pydantic
  • Spring之SSM整合流程详解(Spring+SpringMVC+MyBatis)
  • 【Linux】常用命令(一)