Почему Javascript "in" оператор последовательно медленнее, чем строгий элемент сравнения с undefined?
См. http://jsperf.com/in-vs-member-object-access
По существу, почему проверка if ('bar' in foo) {}
значительно медленнее, чем if (foo.bar !== undefined) {}
?
Ответы
Ответ 1
foo.bar !== undefined
проверяет только те 2 значения, чтобы увидеть, соответствуют ли они.
В то время как 'bar' in foo
должен будет использовать какой-либо механизм для прокрутки свойств foo
, чтобы увидеть, есть ли в нем bar
.
Вот интересный Чтение из Ecma- script
Оператор in
Произведение RelationalExpression: RelationalExpression в ShiftExpression оценивается следующим образом:
1. Оцените реляционное выражение.
2. Вызовите GetValue (Результат (1)).
3. Оцените выражение Shift.
4. Вызовите GetValue (Результат (3)).
5. Если Result (4) не является объектом, вызовите исключение TypeError.
6. Вызов ToString (Результат (2)).
7. Вызвать метод [[HasProperty]] результата (4) с параметром Результат (6).
8. Результат возврата (7).
Оператор Strict Does-not-equal (! ==)
Производство EqualityExpression: EqualityExpression! == RelationalExpression оценивается следующим образом:
1. Оцените выражение равенства.
2. Вызовите GetValue (Результат (1)).
3. Оценка RelationalExpression.
4. Вызовите GetValue (Результат (3)).
5. Выполните сравнение Результат (4) === Результат (2). (См. Ниже).
6. Если Result (5) истинно, верните false. В противном случае верните true.
Ответ 2
Ты прав. Для "bar" in foo
нет смысла быть медленнее, чем foo.bar
.
Единственная причина in
не так быстро, так это то, что он не получал столько внимания от инженеров JIT, сколько гораздо более общий синтаксис foo.bar
.
Особенно в случае вашего теста jsperf, где свойство существует как прямое свойство непосредственно в foo
(а не прототипе), понятно, что 'bar' in foo
не должно быть медленнее, чем foo.bar !== undefined
, Во всяком случае, это должно быть быстрее. Основное различие между ними состоит в том, что на in
можно ответить, даже не проверяя значение свойства!
В случае foo.bar
я ожидаю, что как двигатель V8, так и движок SpiderMonkey обнаружат, что код не делает ничего полезного (то есть он не имеет наблюдаемых эффектов) и полностью оптимизирует его. Тест не измеряет никакой реальной работы.
По-видимому, двигатели еще недостаточно умны, чтобы оптимизировать "bar" in foo
, но это всего лишь вопрос времени. И приоритеты.