2012-09-27 24 views
13

Me estaba confundiendo un poco con un experimento mental y ahora estoy buscando algún consejo. Se trata de referencias ECMAscript y el método Array.prototype.indexOf().¿Cómo funciona Javascript's IndexOf() resolver referencias

deja comienzo fácil:

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

Así que ahora empujamos unos "valores primitivos " en nuestra matriz de ECMAScript (ya sea o no que la afirmación es cierta Voy a volver a), por lo al menos lo imaginé así hasta ahora. Una llamada a

container.indexOf(7); 

regresará 1 como se esperaba. La gran pregunta que estoy teniendo es, si .indexOf() realmente compara el valor primitivo o si en realidad se crea 0 se almacena un objeto Number() y se compara su referencia . Esto se convierte en un poco más evidente si se re-escribir que de este modo:

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

var container = [ ]; 

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

container.indexOf(b); 

Hasta este punto, todavía se podría argumentar fácilmente que todos .indexOf() tiene que hacer es comparar los valores, pero ahora veamos algo como esto:

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); 

Aquí, llenamos esa matriz recipiente con objeto referencias y aún así, .indexOf() funciona como espera

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

mientras que una llamada como ésta

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

obviamente vuelve -1 ya que estamos creando un nuevo objeto y obtener una nueva referencia. Entonces aquí debe comparar internamente las referencias entre sí, ¿verdad?

¿Puede algún genio de la especificación de ECMAscript confirmar eso o incluso mejor vincularme algún material al respecto?

Una cuestión lado de esto sería si hay alguna manera de acceder posiblemente un objeto referencia almacenada internamente dentro de un lexicalEnvironment respectivamente Objeto activación.

+0

Si esto funciona en cualquier lugar similar a otros idiomas, a continuación, 'indexOf' funciona en los hashes de objetos donde los objetos suelen tener diferentes valores y objetos primitivos por lo general tienen un hash constante basa en su valor (para enteros, esto a menudo es solo el valor entero en sí). Así que dos objetos int '5' y' 5' tienen el hash '5' y, como tales, son" lo mismo ". – poke

+1

Empecé a escribir una respuesta, pero luego se convirtió en una publicación de blog, así que me detuve y me desanimé de volver a escribirla. Pero si está interesado: http://pastie.org/4828933 – Zirak

Respuesta

8

Se reduce a indexOf() comparando con cada propiedad de matriz a su vez utilizando el mismo algoritmo que el operador ===.

La sección correspondiente de la especificación ECMAScript 5 es la sección 15.4.4.14, paso 9, sección B (mina destacando):

Si kPresent es cierto, entonces

i. Deje que elementK sea el resultado de llamar al método interno [[Get]] de O con el argumento ToString (k).

ii. Deje que el mismo sea el resultado de aplicar el Algoritmo de comparación de igualdad estricta para searchElement y elementK.

iii. Si lo mismo es cierto, devuelve k.

Referencias:

+0

buen mano a mano gracias. Sin embargo, la * comparación de igualdad estricta * descrita allí no describe cómo tratar con objetos en general? Parece que solo describen números, cadenas, booleanos y valores nulos/indefinidos. Además, tengo curiosidad acerca de la primera sección y dice: "* invocando a String() *" en el argumento. Si ese es realmente el 'toString' nativo, entonces todos los objetos deberían devolver * object Object * no? – jAndy

+0

@jAndy: el bit 'ToString (k)' se refiere al nombre de la propiedad, no al valor. La sección de comparación de igualdad estricta describe el algoritmo por completo. Vea el paso 7 en 11.9.6: * "Devuelve true si xey se refieren al mismo objeto. De lo contrario, devuelva false." *. –

2

No estoy seguro de si esto está garantizado en todas las implementaciones de ECMAScript o no, pero el Mozilla documentation indica que utiliza estricta igualdad para hacer la comparación (===). Como tal, esto exhibiría el comportamiento que describe, comparando por valores en primitivos, pero por referencia en objetos (vea strict equality).

+0

Incluso '==' usa la comparación por referencias para objetos. Entonces no tiene nada que ver con la estricta igualdad – zerkms

+3

No digo que sea * debido a * igualdad estricta. Estoy diciendo que en realidad está usando estricta igualdad y eso es consistente con el comportamiento que describe. – Thor84no

0

@Tim Down es correcto. indexOf hace una comparación estricta. Estoy dando una demostración de esta reemplazando valueOf función

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 
Cuestiones relacionadas