Как Javascript indexOf() разрешает ссылки
Я немного смутил себя мысленным экспериментом, и теперь я ищу совет. Его ссылки на ECMAscript и метод Array.prototype.indexOf()
.
Легко начать:
var container = [ ];
// more code
container.push( 5 );
container.push( 7 );
container.push( 10 );
Итак, теперь мы подтолкнули некоторые "примитивные значения" в наш массив ECMAscript (независимо от того, верна ли эта формулировка, я вернусь), по крайней мере, я представлял себе это так. Вызов
container.indexOf( 7 );
вернет 1
, как и ожидалось. Большой вопрос, который у меня возникает, заключается в том, что если .indexOf()
действительно сравнивает примитивное значение или если в действительности создается объект Number()
+, и его сравнивается ссылка. Это становится немного более очевидным, если мы переписываем это так:
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 );
Здесь мы заполнили этот контейнерный массив объектными ссылками и все еще .indexOf()
работает как ожидалось
container.indexOf( b ) // === 1
в то время как такой вызов
container.indexOf({ name: 'b', value: 10 });
очевидно, возвращает -1
, так как мы создаем новый объект и получаем новую ссылку. Итак, здесь он должен внутренне сравнивать ссылки друг с другом, правильно?
Может ли какой-то конкретный класс ECMAscript подтвердить это или даже лучше связать мне какой-то материал об этом?
Побочный вопрос по этому вопросу будет заключаться в том, что есть какой-либо возможный способ доступа к внутренней хранимой объектной ссылке в объекте активации lexicalEnvironment соответственно.
Ответы
Ответ 1
Это сводится к indexOf()
сравнению по сравнению с каждым свойством массива, в свою очередь, с использованием того же алгоритма, что и оператор ===
.
Соответствующий раздел спецификации ECMAScript 5 - это раздел 15.4.4.14, этап 9, раздел b (выделение мин):
Если kPresent истинно, то
я. Пусть elementK является результатом вызова внутреннего метода [[Get]] O с аргументом ToString (k).
II. Пусть это будет результат применения алгоритма сравнения Strict Equality Comparison Algorithm для поискаElement и elementK.
III. Если это верно, верните k.
Литература:
Ответ 2
Я не уверен, что это гарантировано во всех реализациях ECMAScript или нет, но в документации Mozilla говорится, что он использует строгое равенство, чтобы сделать сравнение (===). Таким образом, это проявляет поведение, которое вы описываете, сравнивая значения по примитивам, но ссылаясь на объекты (см. строгое равенство).
Ответ 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