简体   繁体   English

如何用方括号表示法实现这个 curry function "add"?

[英]How do I achieve this curry function "add" with square bracket notation?

My friend sent this picture to me, shows the function add that can chain numbers indefinitely, then output the sum.我朋友发给我这张图,显示可以无限链数的function add ,然后是output求和。

截屏

I was thinking of using Proxy to add key numbers together and rewrite its Symbol.toPrimitive function, but it seems it doesn't work and I'm not sure what is going on...我正在考虑使用Proxy将密钥数字加在一起并重写其Symbol.toPrimitive function,但它似乎不起作用而且我不确定发生了什么......

Am I on the right direction or is there a better way to do it?我的方向是正确的还是有更好的方法?

 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]);

Your problem is that this inside of your [Symbol.toPrimitive](){} method is your proxy, and not your target object (ie: your first object argument to the proxy constructor).您的问题是[Symbol.toPrimitive](){}方法中的this是您的代理,而不是您的target object (即:代理构造函数的第一个 object 参数)。 This causes your proxy get trap to trigger, which results in your toPrimitive method not returning a primitive, but instead an object (and so your code throws).这会导致您的代理获取陷阱触发,从而导致您的toPrimitive方法不返回原语,而是返回 object(因此您的代码抛出)。 This is because, when you perform:这是因为,当您执行:

console.log(+add[1]);

you are converting the Proxy ( add[1] ) to a primitive number value.您正在将代理( add[1] )转换为原始数值。 When this occurs, JavaScript will try and grab the Symbol.toPrimitive function from that proxy.发生这种情况时,JavaScript 将尝试从该代理中获取Symbol.toPrimitive function。 When that occurs, your get trap in your handler object runs, and returns the Symbol.toPrimitive function object defined on your target object. The engine then invokes this returned function with the this value set to the proxy ( not the handler object).发生这种情况时,您的处理程序 object 中的get陷阱将运行,并返回在目标 object 上定义的Symbol.toPrimitive function object。然后引擎调用此返回的 function,并将this设置为代理而不是处理程序对象)。 In code, you can think of the following occurring when JS converts your proxy, add[1] , to a number:在代码中,你可以想到当 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` !!

The above steps are outlined in the spec here .此处的规范中概述了上述步骤。 As you can see from the last line, your Symbol.toPrimitive() function is invoked with this set as your proxy value, which results in the following code also causing your get trap to fire:从最后一行可以看出,调用Symbol.toPrimitive() function 时this设置作为您的代理值,这会导致以下代码也导致您的 get 陷阱触发:

[Symbol.toPrimitive]() {
  return this.value;
}

above, this.value triggers your get method in your handler object to fire with a key of value , as this represents your proxy, causing the get trap to trigger.上面, this.value触发你的处理程序 object 中的get方法以value的键触发,因为this代表你的代理,导致触发 get 陷阱。 Because your get trap returns a proxy when key is set to value , your Symbol.toPrimitive method doesn't return a primitive, but rather it returns your app proxy, which causes your code to throw.因为您的 get 陷阱在key设置为value时返回代理,所以您的Symbol.toPrimitive方法不会返回原语,而是返回您的app代理,这会导致您的代码抛出。 A simple quick fix is to handle the case when value is accessed on your object (note that I've also reset value so that each log doesn't accumulate from the previous):一个简单的快速修复是处理在您的 object 上访问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]);

Another option is to change the toPrimitive function that gets invoked, which you can do by returning a function that wraps your toPrimitive function and invokes it with a new this value that is set to the target object. You can also reset your value count in this new wrapper function:另一种选择是更改被调用的toPrimitive function,您可以通过返回包装您的toPrimitive function 的 function 并使用设置为target object 的新this值调用它来实现。您还可以在此重置您的值计数新包装 function:

 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]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM