如何使用方括号表示法实现此 curry 函数 "add"?
How do I achieve this curry function "add" with square bracket notation?
我朋友发给我的这张图片,显示了可以无限链数,然后输出总和的函数add
。
我想用Proxy
把关键数字加在一起,然后重写它的Symbol.toPrimitive
函数,但是好像不行,我也不知道是怎么回事.. .
我的方向是否正确,或者有更好的方法吗?
let add = new Proxy(
{
[Symbol.toPrimitive]() {
return this.value;
},
value: 0
},
{
get(target, key, receiver) {
if(Symbol.toPrimitive === key) {
return target[Symbol.toPrimitive];
} else if (!isNaN(key)) {
target.value += +key;
}
return add;
},
}
);
console.log(+add[1]);
console.log(+add[1][2][3]);
console.log(+add[10][-5][3][100]);
您的问题是 [Symbole.toPrimitive](){}
方法中的 this
是您的代理,而不是您的 target
对象(即:代理构造函数的第一个对象参数)。这会导致您的代理获取陷阱触发,从而导致您的 toPrimitive
方法不是 returning 原语,而是一个对象(因此您的代码会抛出)。这是因为,当您执行:
console.log(+add[1]);
您正在将代理 (add[1]
) 转换为原始数值。发生这种情况时,JavaScript 将尝试从该代理获取 Symbol.toPrimitive
函数。发生这种情况时,您的处理程序对象中的 get
陷阱将运行,并且 return 是在目标对象上定义的 Symbol.toPrimitive
函数对象。然后引擎调用此 returned 函数,并将 this
值 设置为代理 ( 不是 处理程序对象) .在代码中,你可以想到当 JS 将你的代理 add[1]
转换为数字时会发生以下情况:
const input = add[1]; // your proxy
const exoticToPrim = input[Symbol.toPrimitive]; // gets the Symbol.toPrimitive function from your object
const result = exoticToPrim.call(input, "number"); // !! calls `Symbol.toPrimitive` !!
规范 here 中概述了上述步骤。从最后一行可以看出,调用 Symbol.toPrimitive()
函数时将 this
设置为您的代理值,这会导致以下代码也导致您的 get 陷阱触发:
[Symbol.toPrimitive]() {
return this.value;
}
上面,this.value
触发您的处理程序对象中的 get
方法以 value
键触发,因为 this
代表您的代理,导致 get 陷阱触发。因为当 key
设置为 value
时,您的 get trap return 是代理,所以您的 Symbol.toPrimitive
方法不是 return 原语,而是 returns 你的 app
代理,这会导致你的代码抛出。一个简单的快速修复是处理在您的对象上访问 value
的情况(请注意,我还重置了 value
以便每个日志都不会从以前的日志中累积):
let add = new Proxy(
{
[Symbol.toPrimitive]() {
return this.value;
},
value: 0
},
{
get(target, key, receiver) {
if(key === Symbol.toPrimitive) {
return target[key];
} else if(key === 'value') {
const sum = target[key];
target[key] = 0;
return sum;
} else if (!isNaN(key)) {
target.value += +key;
}
return add;
},
}
);
console.log(+add[1]);
console.log(+add[1][2][3]);
console.log(+add[10][-5][3][100]);
另一种选择是更改被调用的 toPrimitive
函数,您可以通过 return 包装您的 toPrimitive
函数并使用新的 this
设置到 target
对象的值。您还可以在这个新的包装函数中重置您的价值计数:
let add = new Proxy(
{
[Symbol.toPrimitive]() {
return this.value;
},
value: 0
},
{
get(target, key, receiver) {
if(key === Symbol.toPrimitive) {
return (...args) => {
const prim = target[key].apply(target, args);
target.value = 0;
return prim;
};
} else if (!isNaN(key)) {
target.value += +key;
}
return add;
},
}
);
console.log(+add[1]);
console.log(+add[1][2][3]);
console.log(+add[10][-5][3][100]);
我朋友发给我的这张图片,显示了可以无限链数,然后输出总和的函数add
。
我想用Proxy
把关键数字加在一起,然后重写它的Symbol.toPrimitive
函数,但是好像不行,我也不知道是怎么回事.. .
我的方向是否正确,或者有更好的方法吗?
let add = new Proxy(
{
[Symbol.toPrimitive]() {
return this.value;
},
value: 0
},
{
get(target, key, receiver) {
if(Symbol.toPrimitive === key) {
return target[Symbol.toPrimitive];
} else if (!isNaN(key)) {
target.value += +key;
}
return add;
},
}
);
console.log(+add[1]);
console.log(+add[1][2][3]);
console.log(+add[10][-5][3][100]);
您的问题是 [Symbole.toPrimitive](){}
方法中的 this
是您的代理,而不是您的 target
对象(即:代理构造函数的第一个对象参数)。这会导致您的代理获取陷阱触发,从而导致您的 toPrimitive
方法不是 returning 原语,而是一个对象(因此您的代码会抛出)。这是因为,当您执行:
console.log(+add[1]);
您正在将代理 (add[1]
) 转换为原始数值。发生这种情况时,JavaScript 将尝试从该代理获取 Symbol.toPrimitive
函数。发生这种情况时,您的处理程序对象中的 get
陷阱将运行,并且 return 是在目标对象上定义的 Symbol.toPrimitive
函数对象。然后引擎调用此 returned 函数,并将 this
值 设置为代理 ( 不是 处理程序对象) .在代码中,你可以想到当 JS 将你的代理 add[1]
转换为数字时会发生以下情况:
const input = add[1]; // your proxy
const exoticToPrim = input[Symbol.toPrimitive]; // gets the Symbol.toPrimitive function from your object
const result = exoticToPrim.call(input, "number"); // !! calls `Symbol.toPrimitive` !!
规范 here 中概述了上述步骤。从最后一行可以看出,调用 Symbol.toPrimitive()
函数时将 this
设置为您的代理值,这会导致以下代码也导致您的 get 陷阱触发:
[Symbol.toPrimitive]() {
return this.value;
}
上面,this.value
触发您的处理程序对象中的 get
方法以 value
键触发,因为 this
代表您的代理,导致 get 陷阱触发。因为当 key
设置为 value
时,您的 get trap return 是代理,所以您的 Symbol.toPrimitive
方法不是 return 原语,而是 returns 你的 app
代理,这会导致你的代码抛出。一个简单的快速修复是处理在您的对象上访问 value
的情况(请注意,我还重置了 value
以便每个日志都不会从以前的日志中累积):
let add = new Proxy(
{
[Symbol.toPrimitive]() {
return this.value;
},
value: 0
},
{
get(target, key, receiver) {
if(key === Symbol.toPrimitive) {
return target[key];
} else if(key === 'value') {
const sum = target[key];
target[key] = 0;
return sum;
} else if (!isNaN(key)) {
target.value += +key;
}
return add;
},
}
);
console.log(+add[1]);
console.log(+add[1][2][3]);
console.log(+add[10][-5][3][100]);
另一种选择是更改被调用的 toPrimitive
函数,您可以通过 return 包装您的 toPrimitive
函数并使用新的 this
设置到 target
对象的值。您还可以在这个新的包装函数中重置您的价值计数:
let add = new Proxy(
{
[Symbol.toPrimitive]() {
return this.value;
},
value: 0
},
{
get(target, key, receiver) {
if(key === Symbol.toPrimitive) {
return (...args) => {
const prim = target[key].apply(target, args);
target.value = 0;
return prim;
};
} else if (!isNaN(key)) {
target.value += +key;
}
return add;
},
}
);
console.log(+add[1]);
console.log(+add[1][2][3]);
console.log(+add[10][-5][3][100]);