获取Node.js中对象的对象标识符

mrzz3bfm  于 9个月前  发布在  Node.js
关注(0)|答案(2)|浏览(93)

在Ruby中,我们可以调用#__id__#object_id来获取任何对象的唯一对象标识符。
Node.js中的等价物是什么?

  • 具体来说,我希望记录此标识符以调试应用程序,并查看是否正在创建一个或多个对象。*
hl0ma9xz

hl0ma9xz1#

标准ECMAScript不会公开任何返回唯一对象标识符的接口,似乎也没有任何特定于Node.js的API。但是,您可以使用WeakMap自己分配唯一ID:

const objectId = (() => {
  'use strict';

  const objIdMap = new WeakMap;
  let counter = 0n;

  return obj => {
    let ident = objIdMap.get(obj);
    if (ident === void 0) {
      ident = counter++;
      objIdMap.set(obj, ident);
    }
    return ident;
  };
})();

{
  const o = {};
  const op = new Proxy(o, {});

  console.log(
    `an object is #${objectId(o)}`);
  console.log(
    `a proxy is #${objectId(op)}`);

  const oc = { ...o };

  console.log(
    `an object copy is #${objectId(oc)}`);
}

{
  const o = Object.freeze({});

  console.log(
    `a frozen object is #${objectId(o)}`);
  console.log(
    `the same frozen object is #${objectId(o)}`);
}

document.body.dataset.a = 123;
console.log(
  `document.body.dataset is #${objectId(document.body.dataset)}`);
console.log(`dataset contains`, document.body.dataset);

console.log(
  `Object.prototype is #${objectId(Object.prototype)}`);
console.log(
  `a fresh object is #${objectId({})}`);
console.log(
  `another fresh object is #${objectId({})}`);

字符串
这将在遇到对象时为它们分配连续的整数。在实现Symbols as WeakMap keys proposal的引擎中,它还将为符号分配标识符,您可能需要也可能不需要:如果要过滤掉它们,请使用typeof运算符。(如果您 * 确实 * 想要为符号分配标识符,即使在没有实现该建议的引擎中,您也可以回退到Map,但要注意,这些符号将被有效地泄漏。仅将其用作 transient 调试辅助工具。)
如果你真的想做得更好,你可以使用FinalizationRegistry来回收已经被垃圾收集的对象的ID。但是我建议不要这样做,因为如果你最终获得了一些对象的ID,收集了这些对象,然后重新分配了这些ID,并错误地将僵尸ID视为引用新对象,那么它可能会导致混乱。
在其他地方,你可能会遇到其他的解决方案:寄生属性,无论是字符串还是符号键,都不会对不可扩展的对象起作用,可能会改变在其他地方可观察到的对象的状态,无法区分代理和目标,并且经常获得Object.prototype的ID足以完全破坏系统。避免这些。参见下面的原因:

// DO NOT USE this implementation or anything like it
const BAD_objectId = (() => {
  'use strict';

  // const objIdKey = Symbol(); would have been only marginally better
  const objIdKey = '__OBJECT_ID_DO_NOT_USE_OR_YOU_WILL_BE_FIRED';
  let counter = 0n;

  return obj => {
    let ident = obj[objIdKey];
    if (ident === void 0) {
      ident = counter++;
      obj[objIdKey] = ident;
    }
    return ident;
  };
})();

{
  const o = {};
  const op = new Proxy(o, {});

  console.log(
    `an object is #${BAD_objectId(o)}`);
  console.log(
    `a proxy is also #${BAD_objectId(op)}`);

  const oc = { ...o };

  console.log(
    `an object copy is also #${BAD_objectId(oc)}`);
}

try {
  const o = Object.freeze({});

  console.log(
    `a frozen object is #${BAD_objectId(o)}`);
  console.log(
    `the same frozen object is #${BAD_objectId(o)}`);
} catch (e) {
  console.warn(`${e}`);
}

document.body.dataset.a = 123;
console.log(
  `document.body.dataset is #${BAD_objectId(document.body.dataset)}`);
console.log(`dataset contains`, document.body.dataset);

console.log(
  `Object.prototype is #${BAD_objectId(Object.prototype)}`);
console.log(
  `a fresh object is also #${BAD_objectId({})}`);
console.log(
  `another fresh object is also #${BAD_objectId({})}`);

1rhkuytd

1rhkuytd2#

没有任何内置的东西,但是你可以使用Map对象索引来检查它。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

const m = new Map();

// then for each object
if (m.has(object)) {
  console.log('already seen this', m.get(object), 'times');
  m.set(object, m.get(object) + 1);
} else {
  m.set(object, 1);
}

字符串

相关问题