jQuerys $ .trim (), ошибка или плохо написано? - PullRequest
9 голосов
/ 28 июня 2010

$.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

UPDATE

Похоже, вы не можете скопировать и вставить эту строку примера, в некоторых местах эти A0 символы заменяются. Firebug console также заменит символы при вставке, вам нужно создать собственную строку в отдельном html-файле / редакторе, чтобы проверить это.

Ответы [ 3 ]

9 голосов
/ 28 июня 2010

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

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

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

В марте было 2 коммита:


1.4.2 $.trim() функция :

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

1.4.3 $.trim() функция :

//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]+$/;
}
7 голосов
/ 28 июня 2010

Обычно для обрезки должно быть достаточно выражения типа ^\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\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]

5 голосов
/ 28 июня 2010

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

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

Спасибо Andrew за указание на это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...