gpt4 book ai didi

javascript - 代理类的 TypeError - TypeError : 'set' on proxy: trap returned truish for property

转载 作者:搜寻专家 更新时间:2023-11-01 00:20:59 28 4
gpt4 key购买 nike

我在使用 Proxy 类时遇到了这个有趣的错误:

TypeError: 'set' on proxy: trap returned truish for property 'users' which exists in the proxy target as a non-configurable and non-writable data property with a different value

我有一个递归创建代理对象属性的库,其中任何非原始属性都是代理对象本身,等等:

let mcProxy = function (target) {
const mirrorCache = {};
return new Proxy(target, {
set: function (target, property, value, receiver) {
if (mirrorCache[property]) {
throw new Error(`property ${property} has already been set`);
}
mirrorCache[property] = true;
Object.defineProperty(target, property, {
writable: false,
value: (value && typeof value === 'object') ? mcProxy(value) : value
});
return true;
}
});
};

exports.create = function (val) {
val && assert.equal(typeof val, 'object', 'val must be an object');
return mcProxy(val || {});
};

上述库代码的实际使用:

//bash
$ npm install proxy-mcproxy

 // nodejs
let McProxy = require('proxy-mcproxy');
let val = McProxy.create();
val.users = [];
val.users = 3; // kaaaboom..error!

但是当我第一次设置用户属性时,我得到了这个问题标题中的错误!

在我上面的库代码中,mirrorCache 是一种检查属性是否已预先设置的方法。我想做的是抛出一个错误,即使我们没有处于strict模式,所以mirrorCache似乎是必要的所以我自己做簿记。

也许有不同或更好的方法来实现我想要实现的目标?这是我的目标:

  1. 抛出错误即使不在严格模式下也是如此
  2. 每当开发人员重新分配属性时抛出错误。每个分配的属性都应该是不可变的。

最佳答案

查看以下内容,ECMA 规范的第 9.5.9 节:

http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver

引人入胜的读物我相信你会同意的。

我认为这两个关键行是:

  1. Let booleanTrapResult be ToBoolean(Call(trap, handler, «target, P, V, Receiver»)).

和同样深奥的:

  1. If targetDesc is not undefined, then

    a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is false and targetDesc.[[Writable]] is false, then

    i. If SameValue(V, targetDesc.[[Value]]) is false, throw a TypeError exception.

在NOTE部分有这样的相关评论:

Cannot change the value of a property to be different from the value of the corresponding target object property if the corresponding target object property is a non-writable, non-configurable own data property.

该注释试图将其翻译成英文,但并未指明关键细节,即步骤的时间安排。第 9 点是您的 setter (trap) 被调用的位置。不幸的是,它检查属性是否可写的位是第 14 点。因此在执行检查时,属性确实是不可写和不可配置的。

解决此问题的一种方法是通过在 defineProperty 中加入 configurable: true 使属性可配置。我并不完全遵循您的用例,因此我无法判断这是否是一个可以接受的折衷方案。

我也想知道为什么您首先需要将这些属性设置为不可写。如果底层对象将始终通过其代理访问,那么您可以完全控制所有 set 调用。我什至不确定为什么您需要 mirrorCache 而不仅仅是检查该属性是否已经在目标对象中。如果您不能假设对象将始终通过其代理访问,那么您似乎已经输掉了这场战斗,因为属性可以在您一无所知的情况下更改。

这样的东西看起来很接近你想要的:

let mcProxy = function (target) {
return new Proxy(target, {
set: function (target, property, value) {
if (Object.prototype.hasOwnProperty.call(target, property)) {
throw new Error(`property ${property} has already been set`);
}

target[property] = (value && typeof value === 'object') ? mcProxy(value) : value;

return true;
}
});
};

它需要更多调整才能正确使用数组,但我不清楚您希望支持哪些数组方法。

关于javascript - 代理类的 TypeError - TypeError : 'set' on proxy: trap returned truish for property,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46227721/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com