JavaScript - === vs == Операционная производительность - программирование
Подтвердить что ты не робот

JavaScript - === vs == Операционная производительность

Несколько недель назад я прочитал эту тему Is < быстрее, чем < =? относительно операторов сравнения в C. Было сказано, что нет никакой разницы в производительности между < и <=, поскольку они интерпретируются как одни и те же/похожие машинные команды.

В то же время в нашей компании "лучшие практики" было сказано, что мы всегда должны использовать "===" для сравнения вещей вместо "==". Итак, я начал задаваться вопросом, всегда ли это подходит, поскольку я привык использовать "==" и "typeof... ==" и не хочу менять свой способ записи: -]

Обратите внимание, что это относится к JavaScript.

Итак, у меня небольшое исследование, и здесь Какой оператор равен (== vs ===) должен использоваться при сравнении JavaScript? сказано, что:

Это связано с тем, что оператор равенства == имеет тип принуждения... что означает что интерпретатор неявно пытается преобразовать значения, а затем сравнивает.

С другой стороны, тождественный оператор === не делает тип принуждение и, таким образом, оно не преобразует значения значений при сравнении

И я начал задаваться вопросом, означает ли это, что когда я использую оператор "===", я получаю хорошую производительность, поскольку никакие ресурсы не будут потрачены на преобразование операндов. А ведь код превращается в машинные команды, означает ли это, что так же, как нет разницы в C при использовании < и <=, это то же самое на JavaScript и других языках?

4b9b3361

Ответ 1

для js, оператор === вернет true, если используется в строковых типах, и строки являются точно такими же символами. Для объектов он сравнивает ссылки на объекты, а не содержимое.

Из стандарта ECMA:

11.9.6 Алгоритм сравнения строгих равенств Сравнение x === y, где x и y - значения, выражает true или false. Такое сравнение выполняется следующим образом:

  • Если Type (x) отличается от Type (y), верните false.
  • Если тип (x) равен Undefined, верните true.
  • Если Type (x) - Null, верните true.
  • Если Type (x) - Number, то а. Если x является NaN, верните false. б. Если y является NaN, верните false. с. Если x - это то же значение числа, что и y, верните true. д. Если x равно +0, а y равно -0, верните true. е. Если x равно -0 и y равно +0, верните true. е. Вернуть false.
  • Если Type (x) - String, тогда верните true, если x и y - это точно такая же последовательность символов (одинаковая длина и одинаковые символы в соответствующие должности); в противном случае верните false.
  • Если Type (x) является логическим, верните true, если x и y оба true или оба false;

Ответ 2

Во-первых, производительность просто не имеет значения. Для любого реального сценария любой выигрыш в производительности при использовании одного оператора над другим будет бесконечно малым по сравнению с другими узкими местами в коде (обычно манипулирование DOM будет целью номер один).

Во-вторых, во многих случаях == и === будут выполнять точно такие же шаги. Когда типы двух операндов одинаковы (например, две строки или два числа), спецификация ECMAScript имеет одинаковые шаги для двух операторов. Поэтому, если вы наблюдаете разницу в производительности между двумя операторами для операндов одного и того же типа в одном браузере или другой среде, то не гарантируется и даже не вероятность того, что вы увидите похожую разницу в другом браузере.

В случае typeof, как упоминалось в вашем вопросе, два операнда гарантированно будут одного типа (строка), и оба оператора будут делать одно и то же, , поэтому единственные причины отдать предпочтение одному оператору другие стилистические.

Сообщество JS в целом пошло довольно жестко по этому вопросу: консенсус, по-видимому, "никогда не используйте == и !=, если вам не нужно принуждение к типу", что слишком догматично для моих вкусов.

Ответ 3

Я чувствую, что ответ с легко проверяемыми доказательствами будет лучшим.

Эти операции настолько малы, что их сложно протестировать на производительность.

  • == 1648 верно
  • === 1629 верно
  • контрольный тест 1575 верно

Если вы вычли контрольный тест, похоже, что в моем браузере разница в скорости составляет ~ 30%. Если вы сделаете это несколько раз, вы можете получить разные ответы, но, как правило, === подходит быстрее всего, что, я думаю, является лишь свидетельством того, насколько незначительной является разница.

Я думаю, что это в значительной степени подтверждает то, что говорили другие, что разница в производительности - пустая трата времени на размышления, но это также показывает, что === на самом деле быстрее. Надеемся, что этот ответ может сэкономить время других людей, тех, кто просто должен видеть доказательства.

2019 Обновления

2019-04-09 Firefox с улучшенным тестом:

  • == 1383 верно
  • === 1167 верно
  • контрольный тест 429 есть

2019-04-09 Chrome с улучшенным тестом:

  • == 249 верно
  • === 248 верно
  • контрольный тест 248 есть

2019-04-09 Edge с улучшенным тестом:

  • == 22510 верно
  • === 20315 верно
  • контрольный тест 4968 есть

С годами браузеры стали умнее, и, похоже, мой первоначальный тест натолкнулся на классные оптимизации в Chrome и Firefox, что делает его более бесполезным. Я сделал тест более трудным для оптимизации и увеличил количество прогонов, чтобы снова получить значимые результаты. Похоже, === все еще быстрее по всем направлениям. Это, вероятно, все еще бесполезная трата времени.

var testString = "42";
var testString2 = "43";
var testString3 = "42";
var testNumber = 42;
var testNumber2 = 43;
var testNumber3 = 42;

var testObject = {};
var testObject2 = {};
var testObject3 = testObject;


var start = Date.now();
var result = null;
for(var i = 0; i < 200000000; i++){
	result = 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString2 || testNumber == testNumber2 || testObject == testObject2 || 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3 && 
	testString == testString3 && testNumber == testNumber3 && testObject == testObject3
}

console.log("==", Date.now() - start, result);

var start = Date.now();
var result = null;
for(var i = 0; i < 200000000; i++){
	result =
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString2 || testNumber === testNumber2 || testObject === testObject2 || 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3 && 
	testString === testString3 && testNumber === testNumber3 && testObject === testObject3
}
console.log("===", Date.now() - start, result);
var start = Date.now();
var alwaysTrue = true;
var alwaysFalse = false;
for(var i = 0; i < 200000000; i++){
	result = 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysFalse || alwaysFalse || alwaysFalse || 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue && 
	alwaysTrue && alwaysTrue && alwaysTrue
}
console.log("control test", Date.now() - start, result);

Ответ 4

Не имеет значения, какая производительность вы получаете, ===, безусловно, лучший выбор в этом случае. Что-нибудь еще, например, более высокая производительность - это только обледенение на торте. Кроме того, разница в любом случае минимальна.

Ответ 5

Это язык сценариев. Производительность этих операторов не должна иметь большого значения, так что вам следует беспокоиться об этом, потому что там есть множество других вещей, которые потребляют гораздо больше энергии, например, тот факт, что он работает на виртуальной машине, слабо напечатан, работает с HTML DOM внутри браузера...

Кроме того, оба оператора выполняют совершенно разные вещи, поэтому в любом случае нельзя быть взаимозаменяемым с другим.

Тем не менее, я думаю (но не проверял), что === работает быстрее. Причина в том, что ему нужно только сравнить тип, и если это соответствует, сравните необработанные данные. Оператор == будет пытаться преобразовать один тип в другой, если они не совпадают. В большинстве случаев это будет более дорогостоящая операция.

И это удачно, потому что в большинстве случаев === - лучший вариант.:)

Но в любом случае вы можете легко протестировать его (убедитесь, что вы тестируете несколько случаев, как с одним типом, так и с несколькими разными типами), но если вы не знаете, как его протестировать, я бы не стал беспокоиться об этом в целом. Разница, если таковая вообще существует, не собирается вас убивать.

Ответ 6

Разница в производительности незначительна, а это означает, что вы не должны тратить драгоценные мозговые циклы на размышления об этом. Если вы действительно хотите знать, вы должны проверить.

Используйте ===, если у вас нет большой причины не делать этого (возможно, нет).