Лучше ли сравнивать строки с использованием toLowerCase или toUpperCase в JavaScript?

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

Тривиальный пример:

var firstString = "I might be A different CASE";
var secondString = "i might be a different case";
var areStringsEqual = firstString.toLowerCase() === secondString.toLowerCase();

или я должен сделать это:

var firstString = "I might be A different CASE";
var secondString = "i might be a different case";
var areStringsEqual = firstString.toUpperCase() === secondString.toUpperCase();

Кажется, что либо "должен", либо будет работать с ограниченным набором символов, как только английские буквы, так что он будет более надежным, чем другой?

В качестве примечания MSDN рекомендует нормализовать строки в верхнем регистре, но это для управляемого кода (предположительно, С# и F #, но у них есть причудливые StringComparers и базовые библиотеки): http://msdn.microsoft.com/en-us/library/bb386042.aspx

Ответ 1

Пересмотренный ответ

Прошло довольно много времени, когда я ответил на этот вопрос. В то время как культурные проблемы все еще остаются актуальными (и я не думаю, что они когда-либо исчезнут), разработка стандарта ECMA-402 сделала мой первоначальный ответ... устаревшим (или устаревшим?).

Лучшее решение для сравнения локализованных строк, кажется, использует функцию localeCompare() с соответствующими локалями и опциями:

var locale = 'en'; // that should be somehow detected and passed on to JS
var firstString = "I might be A different CASE";
var secondString = "i might be a different case";
if (firstString.localeCompare(secondString, locale, {sensitivity: 'accent'}) === 0) {
    // do something when equal
}

Это позволит сравнить две строки без учета регистра, но с учетом акцента (например, ą != a).
If this is not sufficient for performance reasons, you may want to use either
ą != a).
If this is not sufficient for performance reasons, you may want to use either
ą != a).
If this is not sufficient for performance reasons, you may want to use either
toLocaleUpperCase(), or toLocaleLowerCase(), передавая локаль в качестве параметра:

if (firstString.toLocaleUpperCase(locale) === secondString.toLocaleUpperCase(locale)) {
    // do something when equal
}

В теории не должно быть различий. На практике тонкие детали реализации (или отсутствие реализации в данном браузере) могут дать разные результаты...

Оригинальный ответ

Я не уверен, что вы действительно хотели задать этот вопрос в теге Интернационализация (i18n), но так как вы сделали...
Вероятно, самый неожиданный ответ: ни один.

Существует множество проблем с преобразованием регистра, что неизбежно приводит к функциональным проблемам, если вы хотите преобразовать регистр символов без указания языка (как в случае JavaScript). Например:

  1. Есть много естественных языков, которые не имеют понятия upper- и строчных букв. Нет смысла пытаться конвертировать их (хотя это сработает).
  2. Существуют специфические для языка правила для преобразования строки. Немецкий острый S- символ (ß) обязательно должен быть преобразован в две заглавные буквы S (SS).
  3. Турецкий и азербайджанский (или азербайджанский, если хотите) имеет "очень странную" концепцию двух символов i: без точки ı (которая преобразуется в прописные буквы I) и точки я (которая преобразуется в заглавные буквы İ <- этот шрифт не допускает правильного представления, но это действительно другой глиф).
  4. Греческий язык имеет много "странных" правил обращения. Одно конкретное правило касаемо прописной буква сигмы (Е), которые в зависимости от места в слове есть два строчных двойники: регулярная сигма (σ) и конечная сигма (q). Существуют также другие правила преобразования в отношении "акцентированных" символов, но они обычно опускаются при реализации функции преобразования.
  5. В некоторых языках есть заглавные буквы, т.е. Lj, которые должны быть преобразованы в такие вещи, как LJ или менее подходящим образом LJ. То же самое можно сказать и о лигатурах.
  6. Наконец, есть много символов совместимости, которые могут означать то же, что и то, с чем вы пытаетесь сравнить, но состоять из совершенно разных символов. Что еще хуже, такие вещи, как "ae", могут быть эквивалентны "ä" на немецком и финском языках, но эквивалентны "æ" на датском.

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

Ответ 2

Это никогда не зависит от браузера, поскольку это только javascript, который задействован. оба будут давать производительность, основанную на отсутствии символов, которые нужно изменить (флип-фут)

var areStringsEqual = firstString.toLowerCase() === secondString.toLowerCase();
var areStringsEqual = firstString.toUpperCase() === secondString.toUpperCase();

Если вы используете тест, подготовленный @adeneo, вы можете почувствовать его зависимым от браузера, но сделать некоторые другие тестовые входы, такие как "AAAAAAAAAAAAAAAAAAAAAAAAAAAA" и "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" и сравнить.

Производительность Javascript зависит от браузера, если присутствует какой-либо dom api или любая манипуляция/взаимодействие с dom, иначе для всех простых javascript он даст такую ​​же производительность.