4

Trying out the new Proxy objects, I am surprised that when a proxy is set the key is automatically converted to a string:

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

There I would expect that typeof key would be number, since I am passing it a number. However, it gets converted to a string inside Proxy somehow and the actual alerted type is string. You can see a small JSFiddle here that showcases the problem. arr is still an Array even after passing it through the proxy.

So, how could I differentiate from passing a string and a number? I could just regex it out as in /\d+/.test(key), however it'd not differentiate between these situations and it just feels like a hack:

arr['1'];
arr[1];
Francisco Presencia
  • 8,732
  • 6
  • 46
  • 90
  • 2
    The property name is converted to a string even before the value of the property access is determined, i.e. there is no way for a proxied object to know what the original value was. See the spec: http://www.ecma-international.org/ecma-262/7.0/#sec-property-accessors-runtime-semantics-evaluation – Felix Kling Oct 05 '16 at 17:22
  • Coincidentally, native array won't differentiate between `arr['1']` and `arr[1]`, too, for the reason that is explained in the answer. So yes, `/^\d+$/` should be used. See http://stackoverflow.com/a/39802685/3731501 for the example. – Estus Flask Oct 05 '16 at 17:37

1 Answers1

3

Property keys can be only strings or symbols. If you're using something different, like a number, it always gets converted to a string first. Therefore, when using a Proxy you can't distinguish between these two operations:

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

Both of them will trigger the Proxy get handler with '1' as the property key.


Also, the fact that you're using an array doesn't change anything―it works the same with arrays (which are special kind of objects) as it works with plain objects.


See also The Object Type in the specification.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • Perfect, thank you. With your first sentence I also found more relevant info: http://stackoverflow.com/questions/2940424/valid-javascript-object-property-names#comment32771282_2940427 (and link to MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties ). So basically it's accessing the array itself which is converting it to an string, nothing to do with the Proxy. – Francisco Presencia Oct 05 '16 at 17:23
  • It's worth noting that I solved it with a simple `if (key in lists) return lists[key];`, which will catch both generic array methods such as `.forEach()`, `.map()`, etc as well as said numberic indexes – Francisco Presencia Oct 05 '16 at 17:25