JavaScript Object Id [duplicate]

2019-01-10 11:00发布

This question already has an answer here:

Do JavaScript objects/variables have some sort of unique identifier? Like Ruby has object_id. I don't mean the DOM id attribute, but rather some sort of memory address of some kind.

6条回答
再贱就再见
2楼-- · 2019-01-10 11:08

Using ES6 + Symbols.

Use ES6 Module export for Symbol if unique symbol is preferred, otherwise go with Symbo

(function () {
    let id = 0;
    const generateId = () => ++id;

    // export const identifier = Symbol('identifier'); 
    const identifier = Symbol.for('identifier');

    Object.prototype[identifier] = function () {
        const id = generateId();
        this.id = this.id || id;
        return this.id;
    };

})();
查看更多
老娘就宠你
3楼-- · 2019-01-10 11:16

If you want to lookup/associate an object with a unique identifier without modifying the underlying object, you can use a WeakMap:

// Note that object must be an object or array,
// NOT a primitive value like string, number, etc.
var objIdMap=new WeakMap, objectCount = 0;
function objectId(object){
  if (!objIdMap.has(object)) objIdMap.set(object,++objectCount);
  return objIdMap.get(object);
}

var o1={}, o2={}, o3={a:1}, o4={a:1};
console.log( objectId(o1) ) // 1
console.log( objectId(o2) ) // 2
console.log( objectId(o1) ) // 1
console.log( objectId(o3) ) // 3
console.log( objectId(o4) ) // 4
console.log( objectId(o3) ) // 3

Using a WeakMap ensures that the objects can still be garbage-collected.

查看更多
在下西门庆
4楼-- · 2019-01-10 11:17

Using ES6 + Symbols.

Use ES6 Module export for Symbol if unique symbol is preferred, otherwise go with Symbols in global registry.

(function () {
    let id = 0;
    const generateId = () => ++id;

    // export const identifier = Symbol('identifier'); //unique symbol
    const identifier = Symbol.for('identifier'); //symbol in global registry

    Object.prototype[identifier] = function () {
        const id = generateId();
        this.id = this.id || id;
        return this.id;
    };

})();
查看更多
贼婆χ
5楼-- · 2019-01-10 11:18

I've just come across this, and thought I'd add my thoughts. As others have suggested, I'd recommend manually adding IDs, but if you really want something close to what you've described, you could use this:

var objectId = (function () {
    var allObjects = [];

    var f = function(obj) {
        if (allObjects.indexOf(obj) === -1) {
            allObjects.push(obj);
        }
        return allObjects.indexOf(obj);
    }
    f.clear = function() {
      allObjects = [];
    };
    return f;
})();

You can get any object's ID by calling objectId(obj). Then if you want the id to be a property of the object, you can either extend the prototype:

Object.prototype.id = function () {
    return objectId(this);
}

or you can manually add an ID to each object by adding a similar function as a method.

The major caveat is that this will prevent the garbage collector from destroying objects when they drop out of scope... they will never drop out of the scope of the allObjects array, so you might find memory leaks are an issue. If your set on using this method, you should do so for debugging purpose only. When needed, you can do objectId.clear() to clear the allObjects and let the GC do its job (but from that point the object ids will all be reset).

查看更多
甜甜的少女心
6楼-- · 2019-01-10 11:19

Actually, you don't need to modify the object prototype. The following should work to 'obtain' unique ids for any object, efficiently enough.

var __next_objid=1;
function objectId(obj) {
    if (obj==null) return null;
    if (obj.__obj_id==null) obj.__obj_id=__next_objid++;
    return obj.__obj_id;
}
查看更多
Lonely孤独者°
7楼-- · 2019-01-10 11:25

No, objects don't have a built in identifier, though you can add one by modifying the object prototype. Here's an example of how you might do that:

(function() {
    var id = 0;

    function generateId() { return id++; };

    Object.prototype.id = function() {
        var newId = generateId();

        this.id = function() { return newId; };

        return newId;
    };
})();

That said, in general modifying the object prototype is considered very bad practice. I would instead recommend that you manually assign an id to objects as needed or use a touch function as others have suggested.

查看更多
登录 后发表回答