JavaScript 中是否有身份标识索引值?

18

在JavaScript中,可以像以下方式对对象和数组的值进行索引:objOrArray[index]。是否存在一个唯一的“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

在这个上下文中,“identity”(身份)的定义是: https://en.wikipedia.org/wiki/Identity_function


2
除非有一个元素(键控或索引),它本身指向容器,否则表达式永远不会为真(如所示代码)。 - user2864740
8
我投票关闭此问题,因为所有数学术语并不一定在计算机科学中都有应用。 - Mister Jojo
4
创建这个假设的“身份”索引的一种方法是:a = [1,2,3]; a.myself = a; x = "myself"; a[x] === a..(仅当x的值为所示时,才为真)。 - user2864740
23
这个问题正在元社区上讨论。 - cigien
3
首先,substr方法已经被弃用,请不要使用该方法。其次,s.description.substring(0, 50)不需要进行length检查。我不明白“identity”在这里有什么作用。这不再是属性访问,而是条件运算符——两个完全不同的运算符。 - Sebastian Simon
显示剩余4条评论
2个回答

31

没有内置此功能,因为很少有这种需要(有时甚至是反对需要)。0不过,您仍然可以自己创建“身份”密钥:

const self = Symbol('self');

Object.defineProperty(Object.prototype, self, {
    enumerable: false,
    get() { "use strict"; return this; }
});

这将适用于所有基元(除了null和undefined)和大多数JavaScript对象:也就是说,除了代理或通过例如Object.create(null)绕过常规原型链的对象。原型链中后面的任何对象也将能够禁用该功能,例如通过执行{[self]: void 0}来实现;所有这些警告意味着x[self] === x绝不是一条普遍的法则。但这可能是你能做的最好的。

修改Object.prototype通常被认为是一个坏主意,但上述方法设法避免了大部分的问题:在一个符号键上添加属性(并且明确地使其不可枚举),可以防止它在迭代和查找中意外出现,从而有助于确保没有代码会受到影响,除非明确寻找此属性。


0 即使存在这样的功能,它对提问者的原始使用案例也不是一个好的解决方案:‘将字符串裁剪为50个字符或者取整个字符串(如果更短)’的操作可以表示为s.description.substring(0, s.description.length > 50 ? 50 : void 0)(或者实际上只是s.description.substring(0, 50))。即使有这样的功能,表达起来也不会更容易:根据条件,您仍然需要调用substring方法,而不仅仅是查找它,但是不要调用非方法的‘self’。并且,由于在前一种情况下需要在末尾添加省略号,因此您仍然需要在substring调用之外执行条件检查,使任何缩写都变得无效。虽然如此,像本答案中描述的技巧确实有一些真实的用途


1
但是上述代码设法避免了大部分问题。值得一提的是,如果出现以下情况,它可能会“崩溃”。如果由于某种原因,有人使用了 Object.getOwnPropertySymbols(obj.constructor.prototype),他们将看到 self 符号。我不认为人们会写这样的代码。 - Qix - MONICA WAS MISTREATED

19

索引操作没有恒等元素。索引的定义域和值域不一定相同--定义域是数组和对象,但值域可以是任何类型的对象,因为数组元素和对象属性可以持有任何类型。如果你有一个整数数组,那么定义域是 Array,而值域是 Integer,因此不存在唯一的恒等元素。a[x]将始终是一个整数,它永远无法等于数组本身。

即使你有一个由数组构成的数组,也没有理由期望其中任何一个元素是对数组本身的引用。像这样创建自引用数组是可能的,但大多数情况下并不会这样做。即使存在自引用,它也可以在任何索引中出现,因此不存在唯一的恒等值。


1
嗯,有一个Symbol值,它在技术上是对象的索引,但不提供任何实际值。 - Shivam
6
@Shivam 不确定这与什么有关。 - Barmar
1
@Shivam的“the range is Integer”是指a[x],而不是xx始终是一个符号或被强制转换为字符串。 - Sebastian Simon
1
我知道,但如果 x 是一个符号,则该范围不应适用于它。 - Shivam
2
这需要更多的澄清... 1.你的a是一个数组(即一个对象),你的b是一个对象(_this_是域)。2.x可以是符号或字符串。3.a[x]b[x]可以是任何东西——这是范围,而不是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]就是未定义的。 - Sebastian Simon
5
索引的定义域和值域不一定相同,在动态类型、动态分派语言中并不是障碍,因为可以向对象添加任意属性。而原型链也使第二个障碍变得无关紧要。 - user3840170

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接