$ jQuerys .trim (), ошибка или плохо записанный?

$.trim() использует следующий RegExp для обрезки строки:

/^(\s|\u00A0)+|(\s|\u00A0)+$/g

Как оказалось, это может быть довольно ужасно, Пример:

var mystr = '    some test --          more text            new test                                         xxx';
mystr = mystr.replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g, "");

Этот код подвешивает Firefox и Chrome, он просто берет как навсегда".mystr"содержит пробелы, но главным образом hex 160(A0) персонажи. Эта "проблема" действительно только происходит, если нет никакого предварительного ожидания whitespace/A0, но где-нибудь в строке. У меня нет подсказки, почему это происходит.

Это выражение:

/^[\n\r\t \xA0]+|[\n\r\t \xA0]$/g

просто хорошо работает во всех протестированных сценариях. Возможно, лучший шаблон для этого?

Источник: http://code.jquery.com/jquery-1.4.2.js

ОБНОВЛЕНИЕ

Похоже, что Вы не можете copy&paste эта строка в качестве примера в некоторых точках они A0 символы заменяются. Firebug console также заменит символы на вставке, необходимо создать собственную строку в sepperate файле/редакторе HTML для тестирования этого.

9
задан jAndy 28 June 2010 в 13:30
поделиться

3 ответа

Это известная ошибка, как сказано в комментариях, и Crescent прав в том, что это так в 1.4.2, но это уже исправлено в следующем релизе.

Вы можете проверить скорость работы String.prototype.trim на вашей строке здесь: http://jsfiddle.net/dLLVN/
Я получаю около 79 мс в Chrome 117 мс в Firefox для миллиона запусков... так что это исправит проблему зависания :)

Что касается исправления, взгляните на текущий исходник, который будет в 1.4.3, теперь используется родная обрезка.

В марте было 2 коммита для этого:


1.4.2 $.trim() function:

trim: function( text ) {
    return (text || "").replace( rtrim, "" );
},

1.4.3 $. trim() function:

//earlier: 
trim = String.prototype.trim

//new trim here
trim: trim ?
  function( text ) {
    return text == null ?
      "" : 
      trim.call( text ); 
  } :

  // Otherwise use our own trimming functionality
  function( text ) { 
    return text == null ? 
      "" :
      text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
  }

Значения trimLeft и trimRight меняются в зависимости от того, в IE вы или нет, вот так:

trimLeft = /^\s+/,
trimRight = /\s+$/,

// Verify that \s matches non-breaking spaces
// (IE fails on this test)
if ( !/\s/.test( "\xA0" ) ) {
  trimLeft = /^[\s\xA0]+/;
  trimRight = /[\s\xA0]+$/;
}
9
ответ дан 4 December 2019 в 10:03
поделиться

Обычно выражения типа ^ \ s + | \ s + $ должно быть достаточно для обрезки, поскольку \ s должен соответствовать всем пробелам, четные \ 0xa0 неразрывные пробелы 1 . Это выражение должно выполняться без каких-либо проблем.

Возможно, какой-то браузер, который хочет поддерживать jQuery, не соответствует \ 0xa0 с \ s , и для решения этой проблемы jQuery добавил альтернативу (\ s | \ 0xa0) , чтобы удалить неразрывные пробелы и в этом браузере.

С этим изменением вторая часть регулярного выражения выглядит как (\ s | \ 0xa0) + $ , что приводит к проблемам в браузерах, где \ 0xa0 также соответствует \ s . В строке, содержащей длинную последовательность символов \ 0xa0 , каждому символу может соответствовать \ s или \ 0xa0 , что приводит к множеству альтернативных совпадений и экспоненциально много комбинаций, как можно комбинировать разные совпадения. Если эта последовательность \ 0xa0 символов не находится в конце строки, конечное условие $ никогда не может быть выполнено, независимо от того, какие пробелы соответствуют \ s и которые соответствуют \ 0xax , но браузер не знает этого и пробует все комбинации, потенциально ища очень долго.

Предложенного вами упрощенного выражения будет недостаточно, поскольку \ s должен соответствовать всем символам пробела Юникода, а не только хорошо известным символам ASCII.


1 Согласно MDC , \ s эквивалентно [\ t \ n \ v \ f \ r \ u00a0 \ u2000 \ u2001 \ u2002

7
ответ дан 4 December 2019 в 10:03
поделиться

Как оказалось, это поведение было опубликовано в багтрекере jQuerys месяц назад:

http://dev.jquery.com/ticket/6605

Спасибо Эндрю за указание на меня к тому, что.

5
ответ дан 4 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: