JavaScript 中有身份索引值吗?

Shi*_*vam 18 javascript self-reference

在 JavaScript 中,对象和数组的值可以像下面这样进行索引:objOrArray[index]。是否存在身份“索引”值?

换句话说:

是否有一个值x使得以下内容始终为真?

let a = [1, 2, 3, 4];
/* Is this true? */ a[x] == a

let b = { a: 1, b: 2, c: 3 };
/* Is this true? */ b[x] == b
Run Code Online (Sandbox Code Playgroud)

此上下文中身份的定义:https: //en.wikipedia.org/wiki/Identity_function

use*_*170 31

没有这样的内置东西,因为很少需要它(有时甚至不需要它)。0 不过,您可以滚动自己的 \xe2\x80\x98identity\xe2\x80\x99 密钥:

\n
const self = Symbol(\'self\');\n\nObject.defineProperty(Object.prototype, self, {\n    enumerable: false,\n    get() { "use strict"; return this; }\n});\n
Run Code Online (Sandbox Code Playgroud)\n

这将适用于所有原语(除 null 和未定义之外)和大多数 JavaScript 对象:也就是说,除了代理或通过例如 绕过常见原型链的对象之外Object.create(null)。原型链中稍后的任何对象也将能够禁用该功能,例如通过执行{ [self]: void 0 }; 所有这些警告意味着x[self] === x绝不是普遍法则。但这可能是您能做的最好的事情了。

\n

修改Object.prototype通常被认为是一个坏主意,但上面的方法设法避免了它的大部分坏处:在符号键处添加属性(并使其显式不可枚举)可以防止它意外地出现在迭代和查找中原型链,有助于确保不专门查找此属性的代码不会受到影响。

\n
\n

0 即使存在这样的功能,对于提问者\xe2\x80\x99s 的原始用例来说,这也不是一个好的解决方案:将 \xe2\x80\x98 剪切到 50 个字符,或者如果较短\xe2\x80\ 则采用整个字符串x99 操作可以表示为s.description.substring(0, s.description.length > 50 ? 50 : void 0)(或者实际上只是s.description.substring(0, 50))。即使有这样的功能,\xe2\x80\x99 也不会更容易表达:根据条件,你仍然需要调用substring方法,而不仅仅是查找它,而不是调用 \xe2\x80\x98self\ xe2\x80\x99 非方法。考虑到在前一种情况下您需要在末尾附加省略号,您仍然需要在子字符串调用之外执行条件检查,从而使任何简写都变得无效。尽管如此,这个答案中描述的技巧确实有一些实际用途

\n


Bar*_*mar 19

索引操作没有单位元素。索引的域和范围不一定相同——域是数组和对象,但范围是任何类型的对象,因为数组元素和对象属性可以保存任何类型。如果你有一个整数数组,其定义域是Array,而范围是Integer,因此不可能存在恒等式。a[x]永远是一个整数,它永远不能等于数组本身。

即使您有一个数组数组,也没有理由期望任何元素是对数组本身的引用。可以创建像这样的自引用数组,但大多数都不是。即使是这样,自引用也可以位于任何索引中,因此没有唯一的标识值。

  • @Shivam 不确定这有什么关系。 (6认同)
  • “索引的域和范围不一定相同”——在允许向对象添加任意属性的动态类型、动态调度语言中,这是一个愚蠢的无障碍。原型链也使得第二个障碍变得无关紧要。 (5认同)
  • 这需要更多澄清…… 1. 你的“a”是一个数组(即对象),你的“b”是一个对象(_this_ 是域)。2. `x` 可以是符号,也可以是字符串。3. `a[x]` 和 `b[x]` 可以是任何东西 - _this_ 是范围,而不是 `x`。如果“x”是“0”、“1”、“2”、“3”或“length”之一,则“a[x]”是一个数字。如果“x”是“Object.getOwnPropertyNames(Array.prototype)”或“Object.getOwnPropertyNames(Object.prototype)”中的剩余字符串之一,或者是“Object.getOwnPropertySymbols(Array.prototype)”中的符号,则“ a[x]` 始终是一个对象。如果“x”是其他值,则“a[x]”是未定义的。 (2认同)