【问题标题】:Proxy index gets converted to string代理索引被转换为字符串
【发布时间】:2024-04-16 03:30:02
【问题描述】:

试用新的Proxy objects,令我惊讶的是,当设置代理时,密钥会自动转换为字符串:

var arr = ['a', 'b', 'c'];

arr = new Proxy(arr, {
  get: (original, key) => {
    alert(typeof key);
    return original[key];
  }
});

arr[1];  // expected an alert with 'number'; got 'string' instead

我希望typeof keynumber,因为我传递了一个数字。但是,它会以某种方式转换为Proxy 中的字符串,并且实际的警报类型是string。您可以see a small JSFiddle here 展示问题。 arr 通过代理后仍然是一个数组。

那么,我如何区分传递字符串和数字?我可以像 /\d+/.test(key) 一样将其正则表达式,但是它不会区分这些情况,感觉就像一个黑客:

arr['1'];
arr[1];

【问题讨论】:

  • 属性名称甚至在属性访问的值确定之前就被转换为字符串,即代理对象无法知道原始值是什么。请参阅规范:ecma-international.org/ecma-262/7.0/…
  • 巧合的是,由于答案中解释的原因,本机数组也不会区分 arr['1']arr[1]。所以是的,应该使用/^\d+$/。示例见*.com/a/39802685/3731501

标签: javascript ecmascript-6 es6-proxy


【解决方案1】:

属性键只能是字符串或符号。如果您使用不同的东西,例如数字,它总是首先转换为字符串。因此,在使用 Proxy 时,您无法区分这两种操作:

arr['1'];
arr[1];

它们都会以'1' 作为属性键触发代理获取处理程序。


此外,您使用数组这一事实并没有改变任何东西——它对数组(一种特殊类型的对象)的工作方式与对普通对象的工作方式相同。


另见The Object Type in the specification

【讨论】:

  • 完美,谢谢。通过您的第一句话,我还找到了更多相关信息:*.com/questions/2940424/…(并链接到 MDN:developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…)。所以基本上它是在访问将它转换为字符串的数组本身,与代理无关。
  • 值得注意的是,我用一个简单的if (key in lists) return lists[key]; 解决了这个问题,它可以同时捕获通用数组方法,例如.forEach().map() 等以及所述的数字索引