【问题标题】:How does Javascript's indexOf() resolve referencesJavascript 的 indexOf() 如何解析引用
【发布时间】:2012-09-19 02:32:51
【问题描述】:

我对一个思想实验有点困惑,现在我正在寻找一些建议。它是关于 ECMAscript 引用和Array.prototype.indexOf() 方法的。

让我们开始吧:

var container = [ ];
// more code
container.push( 5 );
container.push( 7 );
container.push( 10 );

所以现在我们将一些“原始值”推入到我们的 ECMAscript 数组中(无论该声明是否正确,我都会回来讨论),至少到目前为止我是这样想象的。来电

container.indexOf( 7 );

将按预期返回1。我遇到的一个大问题是,如果 .indexOf() 真的比较原始值,或者实际上是否创建了一个 Number() 对象并存储了它,并且它的 reference 正在被比较。如果我们像这样重写它,这会变得更加明显:

var a = 5,
    b = 7,
    c = 10;

var container = [ ];

container.push( a );
container.push( b );
container.push( c );

container.indexOf( b );

到目前为止,人们仍然可以很容易地认为 .indexOf() 需要做的只是比较值,但现在让我们看看这样的事情:

var a = { name: 'a', value: 5 },
    b = { name: 'b', value: 10 },
    c = { name: 'c', value: 15 };

var container = [ ];
// more code
container.push( a );
container.push( b );
container.push( c );

在这里,我们用 object-references 填充了该容器数组,但 .indexOf() 仍按预期工作

container.indexOf( b ) // === 1

在这样的通话中

container.indexOf({ name: 'b', value: 10 });

显然返回-1,因为我们正在创建一个新对象并获得一个新引用。所以这里它必须在内部相互比较引用,对吧?

一些 ECMAscript 规范天才可以确认或更好地链接我一些关于此的材料吗?

关于此的一个附带问题是,是否有任何可能的方法来访问 lexicalEnvironment 中的内部存储的对象引用,分别为 Activation Object

【问题讨论】:

  • 如果这在与其他语言类似的任何地方都可以工作,那么indexOf 适用于对象散列,其中对象通常具有不同的值,而原始对象通常具有基于其值的恒定散列(对于整数,这是非常通常只是整数值本身)。所以两个 int 对象 55 都有哈希 5,因此是“相同的”。
  • 我开始写一个答案,但后来它变成了一篇博文,所以我停下来,不愿重新写它。但如果你有兴趣:pastie.org/4828933

标签: javascript arrays reference specifications ecmascript-5


【解决方案1】:

我不确定这是否在所有 ECMAScript 实现中都得到保证,但 Mozilla documentation 声明它使用严格相等来进行比较 (===)。因此,这将表现出您描述的行为,通过基元上的值进行比较,但通过对象上的引用进行比较(请参阅strict equality)。

【讨论】:

  • 即使== 也使用对象的引用比较。所以这与严格的平等无关
  • 我并不是说这是因为严格的平等。我是说它实际上是在使用严格的平等,这与他描述的行为是一致的。
【解决方案2】:

归结为indexOf() 使用与=== 运算符相同的算法依次比较每个数组属性。

ECMAScript 5 规范的相关部分是第 15.4.4.14 节,第 9 步,b 节(突出显示我的):

如果 kPresent 为真,那么

我。令 elementK 为使用参数 ToString(k) 调用 O 的 [[Get]] 内部方法的结果。

二。让我们将严格等式比较算法应用于searchElement和elementK的结果相同。

三。如果相同,则返回 k。

参考资料:

【讨论】:

  • 非常感谢。但是,那里描述的严格相等比较没有描述一般如何处理对象?看起来它们只描述数字、字符串、布尔值和空/未定义值。另外,我对第一部分也很好奇,它在参数上说“calling toString()”。如果那真的是原生 toString,那么所有对象都应该返回 object Object no ?
  • @jAndy:ToString(k) 位指的是属性名称,而不是值。严格相等比较部分确实完整地描述了算法。参见 11.9.6 中的步骤 7:“如果 x 和 y 引用同一个对象,则返回 true。否则,返回 false。”.
【解决方案3】:

@Tim Down 是对的。 indexOf 进行严格比较。我通过覆盖valueOf 函数来演示这一点

var MyObject = function(n, v){
   this.name = n;
   this.value = v;
}

MyObject.prototype.valueOf = function(){
    return this.value;
}

var a = new MyObject("a", 5);
var b = new MyObject("b", 10);
var c = new MyObject("c", 15);

var container = [ ];

container.push( a );
container.push( b );
container.push( c );

console.log(b == 10); // true
console.log(container[1] == 10); // true

console.log(b === 10); // false
container.indexOf(10); // -1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    • 2015-03-03
    相关资源
    最近更新 更多