是否可以将javascript引用转换为数字或哈希值?

时间:2014-09-08 10:57:49

标签: javascript node.js

假设你想比较两个javascript对象或数组以获得引用相等。

最明显的解决方案是

if (a === b) { /*...*/ };

这个问题是ab必须保存对实际对象的引用。在同样的情况下,这可能是个问题。例如,尝试在memoization函数中保存实际引用会产生内存泄漏。

一种方法是使用JSON.stringify(a)来获取对象的字符串表示并进行比较。但在某些使用案例中,这可能会非常昂贵。更不用说实际的参考平等没有被考虑在内。

这让我感到疑惑。有没有办法对实际引用进行字符串化而不是对象内容?显然,你不能在javascript中操作指针,但是如果你只能得到某种指针表示怎么办呢。一个哈希值?原始内存位置? Guid或整数表示?

我知道在chrome dev工具中分析内存转储时会有一些对象id-s。也许这些东西可以在运行时访问?在node.js中使用某种特殊的开关?

有人能想到一种在javascript中完成这项工作的方法吗?

2 个答案:

答案 0 :(得分:3)

如果要将其用于记忆(缓存),则应使用ES6 WeakMap。它适用于Firefox 6,Chrome 36和IE 11。

  

WeakMap对象是键/值对的集合,其中键是对象,值可以是任意值。   [...]   经验丰富的JavaScript程序员会注意到,这个API可以用JavaScript实现,它有四个API方法共享的两个数组(一个用于键,一个用于值)。这样的实施将有两个主要的不便之处。第一个是O(n)搜索(n是地图中的键数)。第二个是内存泄漏问题。

它的工作方式类似于Java中的地图 - 您可以将任意对象用作键和值。但是密钥不会阻止垃圾收集,所以你不必担心内存泄漏,但仍然可以找到给定对象的记忆计算。

答案 1 :(得分:0)

受到@ user2864740评论的启发(老兄,设置一个名字,严肃地说: - ))。

  

它也可能只是参与此系统的对象的必需方法

此实现扩展了Object prototype以包含一个实用程序,以便为每个对象生成唯一的UUID。 generateId的实施取自here

似乎正在为对象和数组工作。

Object.prototype._id = function () {
    return this.__id || (this.__id = generateId());

    function generateId() {
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
    }
}

function assert(message, test) {
    if (!test) {
        throw new Error("ASSERTION FAILED: " + message);
    } else {
        console.log("PASSED: " + message);
    }
}


var x = { name: "same" },
    y = { name: "same" },
    z = [],
    x2 = x;

assert("Id is unchanging", x._id() === x._id());
assert("Id is different  for different objects", x._id() !== y._id());
assert("Arrays have id too", z._id() === z._id());
assert("Id is same for same objects", x._id() === x2._id());

Live example

我离开这里,看看是否有问题,或者是否有人有更好的主意。