# Object.at(), Object.size()

**URL:** <https://es.discourse.group/t/object-at-object-size/1533>\
**Category:** 💡 Ideas\
**Created:** [November 24, 2022, 12:36pm UTC](https://es.discourse.group/t/object-at-object-size/1533 "2022-11-24T12:36:12Z")\
**Posts on this page:** 5\
**Page:** 2

<div class="post-metadata">

**Author:** ![clshortfuse](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/clshortfuse/32/1769_2.png) [@clshortfuse](https://es.discourse.group/u/clshortfuse)\
**Post date:** [June 8, 2023, 5:53pm UTC](https://es.discourse.group/t/object-at-object-size/1533/22 "2023-06-08T17:53:37Z")

</div>

The long explanation why Custom Elements can't return `Proxy` is here:

> <https://github.com/WICG/webcomponents/issues/857>
>
> Unfortunately, the following causes an error:
> 
> \`\`\`js
> class A extends HTMLElem…ent {
> constructor() {
> super()
> return new Proxy(this, {
> get(target, key) {
> console.log('get property:' key)
> return target\[key\]
> }
> })
> }
> }
> 
> window.customElements.define('a-element', A)
> \`\`\`
> 
> \`\`\`html
> \<a-element\>\</a-element\>
> \`\`\`
> 
> \`\`\`
> Uncaught DOMException: custom element constructors must call super() first and must not return a different object
> \`\`\`
> 
> Can Custom Elements API be upgraded to support Proxied instances?

The gist is `Proxy` is too limited and the native HTMLElement has internal aspects that aren't exposed via just `get`/`set`.

I'm not as pessimistic about drain performance of objects with the introduction of `Symbol.Indexer`. Basically, all processing of objects can stay the same but it's only that Objects that invoke a setter on `obj[Symbol.Indexer]` would need special processing. For example, all named functioned should be "constructors" but V8 doesn't actually process any of that code until it's required, making them as fast as anonymous/lambda functions. At worst, you've degraded the performance of your object because you used custom indexes, but it shouldn't affect all objects. For some special cases, this may be worth it because there's no alternative\*.

I took a look at V8's [Fast Properties](https://v8.dev/blog/fast-properties) but while it explains the fast paths for object and arrays, it doesn't fully explain how an overloaded `Array` object with custom properties would work:

```js
  const customIndexable = [1,2,3,4];
  customIndexable.customMethod = () => console.log('foo');

```

At best I understood indexed values are stored as an array separately from the dictionary needed for keys anyway:

> Handling of integer indexed properties is no less complex than named properties. Even though all indexed properties are always kept separately in the elements store, [...]

Meaning, the logistics for making it to work sound like it doesn't needs too much refactoring. V8 team already keeps them separate.

\*But of course, I'm talking about my use cases where performance isn't as much as priority as replicating functionality.

* * *

For the original point about keys, I would think to do this with a Map (not including overloaded `constructor` code):

```js
class TrackedMap extends Map {
  #keys = [];

  set(key, value) {
    if (!this.has(key)) {
      this.#keys.push(key);
    }
    return Map.prototype.set.call(this, key, value);
  }

  delete(key, value) {
    const indexOfKey = this.#keys.indexOf(key);
    if (indexOfKey === -1) return false;
    this.#keys.splice(indexOfKey, 1);
    return Map.prototype.delete.call(this, key, value);
  }

  at(index) {
    if (index > this.#keys.length) return undefined;
    if (index < this.#keys.length * -1) return undefined;
    return this.get(this.#keys.at(index));
  }
}

```

FYI, `Chrome` and `Firefox` has a fast path for `Array.indexOf` because it uses a HashMap after a certain point (Safari does not). So, it makes that look up O(1).

And this is just kinda wasteful since `Map.prototype.keys` doesn't allow by index.

* * *

Tying it back, if index number as properties isn't just limited to Arrays, then it paves the way for all collections, including `ReturnType<Map.prototype.keys>` to get index features, instead of polyfill/wrapping as explained above. The check could be `Array.isArray(obj) || Symbol.indexer in obj`.

And just like `myMap.keys()[Symbol.iterator]` is `[native code]`, it can also be a userland function.

---

<div class="post-metadata">

**Author:** ![coolCucumber-cat](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/coolcucumber-cat/32/1892_2.png) [@coolCucumber-cat](https://es.discourse.group/u/coolCucumber-cat)\
**Post date:** [October 25, 2023, 11:48am UTC](https://es.discourse.group/t/object-at-object-size/1533/23 "2023-10-25T11:48:27Z")

</div>

I think there's a much better, indirect solution. First, Object.iterKeys() which would be an iterable of all the keys (not creating them in memory as an array) and then Iterator.prototype.size() and Iterator.prototype.at(). Then you could do Object.iterKeys(x).at(y) or Object.iterKeys(x).size(). It's doing the same thing and those are things people probably want anyway and you could repurpose it for that.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [October 25, 2023, 2:08pm UTC](https://es.discourse.group/t/object-at-object-size/1533/24 "2023-10-25T14:08:01Z")

</div>

Iterators in general don’t have or know a size, so neither of those methods could go on Iterator.prototype.

---

<div class="post-metadata">

**Author:** ![coolCucumber-cat](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/coolcucumber-cat/32/1892_2.png) [@coolCucumber-cat](https://es.discourse.group/u/coolCucumber-cat)\
**Post date:** [October 25, 2023, 2:23pm UTC](https://es.discourse.group/t/object-at-object-size/1533/25 "2023-10-25T14:23:51Z")

</div>

There are already methods like this on Iterator.prototype, like map, reduce, toArray, every, filter, find, so I don't see why not.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [October 25, 2023, 2:35pm UTC](https://es.discourse.group/t/object-at-object-size/1533/26 "2023-10-25T14:35:57Z")

</div>

Each of those operates on one item at a time, and do not need to know the number of yielded objects in advance.

[Previous page](https://es.discourse.group/t/object-at-object-size/1533.md?page=1)
