问题描述
因此,我在研究代理对象,并尝试查看它们如何与扩展语法和解构结构混合使用时,我对这种奇怪的行为感到固执:
So, I was playing around with Proxy objects and while trying to see how they mix with spread syntax and de-structuring, I stubled upon this weird behavior:
const obj = {
origAttr: 'hi'
}
const handler = {
get(target, prop) {
console.log(prop);
return 1;
},
has(target, prop) {
return true;
},
ownKeys(target) {
return [...Reflect.ownKeys(target), 'a', 'b'];
},
getOwnPropertyDescriptor(target, key) {
return {
enumerable: true,
configurable: true
};
}
}
const test = new Proxy(obj, handler);
const testSpread = { ...test};
console.log('Iterate test');
// Works OK, output as expected
for (const i in test) {
console.log(i, ' -> ', test[i]);
}
console.log('Iterate testSpread');
// Also works OK, output as expected
for (const i in testSpread) {
console.log(i, ' -> ', testSpread[i]);
}
console.log('Here comes the unexpected output from console.log:');
console.log(test); // All attributes are 'undefined'
console.log(testSpread); // This is OK for some wierd reason
以上脚本输出(在节点v10.15.1上):
The above script outputs (on node v10.15.1):
这是控制台日志中的意外输出:
Here comes the unexpected output from console log:
Symbol(nodejs.util.inspect.custom)
Symbol(Symbol.toStringTag)
Symbol(Symbol.iterator)
{ origAttr: undefined, a: undefined, b: undefined }
{ origAttr: 1, a: 1, b: 1 }
为什么console.log(test);输出表明对象的属性都是未定义的?如果在调试某些东西时发生,这可能会引起一些严重的头痛.
Why does console.log(test); output show that the attributes of the object are all undefined? This could cause some serious headache if it were to happen when debugging something.
是节点本身还是在console.log的实现中存在错误?
Is it a bug in node itself or perhaps in the implementation of console.log?
推荐答案
好吧,我做了一些进一步的挖掘,并将整个过程追溯到在代理对象上调用Object.getOwnPropertyDescriptor以获得其属性的值.
Okay, I did some more digging and traced the whole thing down to Object.getOwnPropertyDescriptor being called on my proxy object to get the values of its attributes.
但是在我的情况下,"value"属性显然是未定义的,因为我有一个getOwnPropertyDescriptor陷阱,该陷阱仅指定可枚举和可配置的属性(因此可以迭代数组,将其与散布运算符结合使用,依此类推) .
But the "value" attribute is obviously undefined in my case, since I have a trap for getOwnPropertyDescriptor which only specifies the enumerable and configurable attributes (thus making it possible to iterate the array, use it with spread operators and so on).
好吧,正如Bergi在评论中指出的那样,这是一种标准方法.
Well, as Bergi pointed out in the comments, there is a standard way.
也在文档 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Parameters 这绑定到处理程序"
Also in the docs https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Parameters "this is bound to the handler"
编辑我的代码以反映这一点.
Edited my code to reflect that.
展示getOwnPropertyDescriptor行为的代码如下:
The code demonstrating getOwnPropertyDescriptor behavior is below:
const obj = {
origAttr: 'hi'
}
const handler = {
get(target, prop) {
return 1;
},
has(target, prop) {
return true;
},
ownKeys(target) {
return [...Reflect.ownKeys(target), 'a', 'b'];
},
getOwnPropertyDescriptor(target, key) {
return {
value: this.get(target, key),
enumerable: true,
configurable: true
};
}
}
const test = new Proxy(obj, handler);
const testSpread = { ...test
};
// Defined, due to trapped getOwnPropertyDescriptor which returns a value attribute
console.log(Object.getOwnPropertyDescriptor(test, 'origAttr'))
// Defined, because it is a regular object, not a proxy with a getOwnPropertyDescriptor trap
console.log(Object.getOwnPropertyDescriptor(testSpread, 'origAttr'))
这篇关于Javascript代理和传播语法,与console.log结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!