DEV Community

loading...

(kind of) Getting the memory address of a JavaScript object

ArthurJ
・2 min read

Hey everyone,

I am building a library for Graph Object Notation, at the moment in super early stage, and I came across a really nice "loophole" to what I imagined being the biggest obstacle of the project : Getting the memory address of the objects in JavaScript. Here is a nice post if you need a quick reminder on how memory works in JavaScript!

As you may know, you can't access them for security reasons, end of the post, thank you for reading...
...but turns out, you can cheat a little bit there. The actual address isn't really that important in my case, what's important is the consistency of the "fake address" that we will generate and make sure the same object always spits out the same address!

First though is to go on and brute force things, building an array of known Object, another of fake address and comparing every object against that array. Turns out it works, but here comes the slow library judgement.
Second though, building hashes of the object based on properties and values, then only comparing with "same hash" object, works as well, but not really efficient either.

Then came an idea.

The Map object isn't really used in the JavaScript front-end world, but it's really effective at finding if it has a key defined, and it can hold any type of data as a key. This is contrary to the Object object, where keys can only be strings.

1 + 1 = success, let's use the objects themselves as key, and the fake address as value.

Here is a short video on how it works : https://youtu.be/-ZenKpRfJdo

And the next one in a more functional programming style, with a nice triple arrow function : https://youtu.be/r7y8roTIPig

And for those not wanting to watch a video, here's the code :
(the live version is here)[https://gon.arthurj.now.sh/references]

https://codesandbox.io/s/vibrant-northcutt-wkh2e

const user1 = { name: "arthur" };
const users = [user1, { name: "arthur" }, { name: "Joe" }, user1];

//This generator doesn't garantee uniqueness, but looks way more memoryish than a incremental counter
//if you use this code for real, do incremental or something else unique!
function* generator() {
  while (true) {
    const random = Math.random()
      .toString(16)
      .slice(2, 10);
    yield `0x${random}`;
  }
}

const preload = (knowObjects, refs, generate) => (reference = false) => {
  if (reference) {
    return refs;
  } else {
    return object => {
      let address;
      if (knowObjects.has(object)) {
        address = knowObjects.get(object);
      } else {
        address = generate.next().value;
        knowObjects.set(object, address);
        refs[address] = object;
      }
      return address;
    };
  }
};

const setup = preload(new Map(), {}, generator());
const findRef = setup(false);

const array = users.map(u => findRef(u));
/*
console.log something like that, and builds up the knowObjects map / refs object
[
 "0xf094c649",
 "0x7de35306",
 "0x6a99aa2f",
 "0xf094c649"
]
*/

const refs = setup(true);
/*
console.log something like this
{
 "0xf094c649": {
  "name": "arthur"
 },
 "0x7de35306": {
  "name": "arthur"
 },
 "0x6a99aa2f": {
  "name": "Joe"
 }
}
*/
Enter fullscreen mode Exit fullscreen mode

Discussion (2)

Collapse
akozdev profile image
Aleksander Kozłowski • Edited

Thank you for this article. You said that we cannot access addresses due to security reasons. Can you share some more information on that? Maybe you could share some article that talks more about it? Thanks!

Collapse
aelesia profile image
aelesia

I never ever thought I'd need to retrieve a Javascript function based on its pointer, but damn today I did. Thanks for your article!