заканчивается в JavaScript


1103

Как я могу проверить, заканчивается ли строка определенным символом в JavaScript?

Пример: у меня есть строка

var str = "mystring#";

Я хочу знать, заканчивается ли эта строка #. Как я могу это проверить?

  1. Есть ли endsWith()метод в JavaScript?

  2. Одно из решений, которое у меня есть, - взять длину строки, получить последний символ и проверить его.

Это лучший способ или есть другой способ?


5
Это должен быть связанный вопрос: stackoverflow.com/questions/646628/javascript-startswith
Хэмиш Грубиджан

Ответы:


1764

ОБНОВЛЕНИЕ (24 ноября 2015 г.):

Этот ответ первоначально был опубликован в 2010 году (шесть лет назад), поэтому, пожалуйста, примите к сведению эти проницательные комментарии:

  • Shauna - обновление для Googlers. Похоже, ECMA6 добавляет эту функцию. Статья MDN также показывает polyfill. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith

  • TJ Crowder - Создание подстрок не дорого в современных браузерах; возможно, это было в 2010 году, когда был опубликован этот ответ. В наши дни простой this.substr(-suffix.length) === suffixподход является самым быстрым в Chrome, таким же в IE11, как indexOf, и только на 4% медленнее (территория fergetaboutit) в Firefox: jsperf.com/endswith-stackoverflow/14 И быстрее по всем направлениям, когда результат ложен: jsperf.com/endswith-stackoverflow-when-false Конечно, с ES6 добавление заканчивается, суть спорная. :-)


ОРИГИНАЛЬНЫЙ ОТВЕТ:

Я знаю, что это годичный вопрос ... но мне это тоже нужно, и мне нужно, чтобы он работал кросс-браузерно, так что ... объединяя ответы и комментарии каждого и немного упрощая его:

String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
  • Не создает подстроку
  • Использует встроенную indexOfфункцию для самых быстрых результатов
  • Пропустить ненужные сравнения, используя второй параметр, indexOfчтобы пропустить вперед
  • Работает в Internet Explorer
  • НЕТ регулярных выражений

Также, если вам не нравится вставлять вещи в прототипы нативной структуры данных, вот отдельная версия:

function endsWith(str, suffix) {
    return str.indexOf(suffix, str.length - suffix.length) !== -1;
}

РЕДАКТИРОВАТЬ: Как отметил @hamish в комментариях, если вы хотите ошибиться на всякий случай и проверить, была ли уже реализована реализация, вы можете просто добавить typeofпроверку следующим образом:

if (typeof String.prototype.endsWith !== 'function') {
    String.prototype.endsWith = function(suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}

42
Обновление для Googlers. Похоже, ECMA6 добавляет эту функцию. Статья MDN также показывает polyfill. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Шона

2
@ lukas.pukenis он пропускает до конца и проверяет только один экземпляр суффикса в самом конце. не имеет значения, появляется ли строка поиска в другом месте.
Чакрит

3
Добавление проверки для ситуации, когда аргумент "суффикс" не определен ": if (typeof String.prototype.endsWith! == 'function') {String.prototype.endsWith = function (суффикс) {вернуть this.indexOf (суффикс) , this.length - ((суффикс && суффикс.length) || 0))! == -1;};}
Мандип

2
Какие осложнения регулярных выражений вы упомянули?
IcedDante

5
Создание подстрок не дорого в современных браузерах; возможно, это было в 2010 году, когда был опубликован этот ответ. В наши дни простой this.substr(-suffix.length) === suffixподход является самым быстрым в Chrome, таким же в IE11 indexOfи только на 4% медленнее (территория fergetaboutit) в Firefox: jsperf.com/endswith-stackoverflow/14 И быстрее по всем направлениям, когда результат ложен: jsperf .com / EndsWith-StackOverflow-когда-ложь конечно, с ES6 добавления endsWith, точка является спорным. :-)
TJ Crowder

295
/#$/.test(str)

будет работать во всех браузерах, не требует внесения исправлений обезьяны Stringи не требует сканирования всей строки, как lastIndexOfпри отсутствии совпадений.

Если вы хотите сопоставить константную строку, которая может содержать специальные символы регулярного выражения, такие как '$', то вы можете использовать следующее:

function makeSuffixRegExp(suffix, caseInsensitive) {
  return new RegExp(
      String(suffix).replace(/[$%()*+.?\[\\\]{|}]/g, "\\$&") + "$",
      caseInsensitive ? "i" : "");
}

и тогда вы можете использовать это так

makeSuffixRegExp("a[complicated]*suffix*").test(str)

10
Это удобно и просто, если вы проверяете постоянную подстроку.
Уоррен Бланшет

1
lastIndexOf сканирует всю строку? Я думал, что это будет искать с конца до начала.
Том Брито,

3
@TomBrito, lastIndexOfсканирует всю строку, только если не находит совпадений или находит совпадение в начале. Если в конце есть совпадение, оно работает пропорционально длине суффикса. Да, /asdf$/.test(str)дает истину, когда strзаканчивается "asdf".
Майк Самуэль,

3
@ Том Брито, это буквальное выражение. Синтаксис заимствован из Perl. См developer.mozilla.org/en/Core_JavaScript_1.5_Guide/... или ненужный уровень детализации, смотрите раздел 7.8.5 спецификации ECMAScript языка.
Майк Сэмюэл

2
+1 за кросс-браузерную совместимость. Протестировано на Chrome 28.0.1500.72 m, Firefox 22.0 и IE9.
Адриен Бе

91
  1. К сожалению нет.
  2. if( "mystring#".substr(-1) === "#" ) {}

14
@ Энтони, эм ... так что пользуйся .Length-1, в чем проблема? if (mystring.substr (mystring.length-1) === "#") {} прекрасно работает в IE.
BrainSlugs83

12
@ BrainSlugs83 - в этом и заключается проблема: синтаксис «.length-1» работает в IE, а синтаксис «-1» - нет. Об этом нужно помнить, поэтому +1 к Энтони за подсказку.
Аврамов

2
Не могли бы вы использовать slice()? Это работает для меня в моем быстром тесте IE7.
Алекс

Freaken IE. когда он умрет?
ahnbizcad

67

Да ладно, это правильная endsWithреализация:

String.prototype.endsWith = function (s) {
  return this.length >= s.length && this.substr(this.length - s.length) == s;
}

Использование lastIndexOfтолько создает ненужные циклы ЦП, если нет совпадения.


2
Согласовано. Я действительно чувствую, что это самое эффективное решение, предлагаемое, так как оно имеет раннюю проверку прерываний / здравомыслия, оно короткое и лаконичное, элегантное (перегружает прототип строки), и подстрока кажется гораздо меньшим ресурсным ударом, чем раскрутка движка регулярных выражений.
BrainSlugs83

Также нравится это решение. Просто название функции введено неправильно. Должно быть "заканчивается".
xmedeko

3
@ BrainSlugs83 Прошло несколько лет, но теперь этот метод не быстрее, чем метод indexOf, упомянутый выше в chakrit, а в Safari он на 30% медленнее! Вот тест jsPerf для случая сбоя около 50-символьной строки: jsperf.com/endswithcomparison
Brent Faust

4
Вероятно, следует использовать, ===хотя.
Тимммм

56

Эта версия избегает создания подстроки и не использует регулярные выражения (некоторые ответы регулярных выражений здесь будут работать, другие не работают):

String.prototype.endsWith = function(str)
{
    var lastIndex = this.lastIndexOf(str);
    return (lastIndex !== -1) && (lastIndex + str.length === this.length);
}

Если для вас важна производительность, стоит проверить, lastIndexOfдействительно ли это быстрее, чем создание подстроки или нет. (Это может зависеть от того, какой движок JS вы используете ...) Он может быть быстрее в подходящем случае, и когда строка мала, но когда строка огромна, ей нужно оглянуться через все это, даже если хотя нам все равно :(

Для проверки одного символа, charAtвероятно, лучше всего найти длину, а затем использовать ее.


2
Если this.lastIndexOf () возвращает -1, вы можете попасть в случаи, когда он возвращает true в зависимости от this.length и str.length. Добавьте тест, который lastIndexOf ()! = -1.
ebruchez

1
Почему метод регулярных выражений не работает?
IZB

2
@izb: Ответы, которые старше моих, которые пытаются использовать str+"$"в качестве регулярного выражения, не работают, так как они могут быть недопустимыми регулярными выражениями.
Джон Скит

26

Не видел apporach с sliceметодом. Так что я просто оставлю это здесь:

function endsWith(str, suffix) {
    return str.slice(-suffix.length) === suffix
}

1
Вы можете упростить это немного больше: return str.slice (-1) === суффикс;
Эрик К.

2
Это лучший ответ. Не уверен, почему у него нет больше голосов.
Nutitide

17
return this.lastIndexOf(str) + str.length == this.length;

не работает в случае, когда длина исходной строки на единицу меньше длины строки поиска и строка поиска не найдена:

lastIndexOf возвращает -1, затем вы добавляете длину строки поиска, и у вас остается длина исходной строки.

Возможное исправление

return this.length >= str.length && this.lastIndexOf(str) + str.length == this.length

30
Вы получили значок «Обнаружил ошибку в ответе Джона Скита». Смотрите свой профиль для деталей.
Бобинц

17

От developer.mozilla.org String.prototype.endsWith ()

Резюме

endsWith()Метод определяет , является ли строка заканчивается символами другой строки, возвращая истинным или ложным в зависимости от обстоятельств.

Синтаксис

str.endsWith(searchString [, position]);

параметры

  • searchString : символы для поиска в конце этой строки.

  • position : Искать в этой строке, как если бы эта строка была только этой длинной; по умолчанию - фактическая длина этой строки, ограниченная в диапазоне, установленном длиной этой строки.

Описание

Этот метод позволяет определить, заканчивается ли строка другой строкой.

Примеры

var str = "To be, or not to be, that is the question.";

alert( str.endsWith("question.") );  // true
alert( str.endsWith("to be") );      // false
alert( str.endsWith("to be", 19) );  // true

Характеристики

Спецификация языка ECMAScript, 6-е издание (ECMA-262)

Совместимость браузера

Совместимость браузера



8
String.prototype.endsWith = function(str) 
{return (this.match(str+"$")==str)}

String.prototype.startsWith = function(str) 
{return (this.match("^"+str)==str)}

надеюсь, это поможет

var myStr =   Earth is a beautiful planet  ”;
var myStr2 = myStr.trim();  
//==“Earth is a beautiful planet”;

if (myStr2.startsWith(“Earth”)) // returns TRUE

if (myStr2.endsWith(“planet”)) // returns TRUE

if (myStr.startsWith(“Earth”)) 
// returns FALSE due to the leading spaces…

if (myStr.endsWith(“planet”)) 
// returns FALSE due to trailing spaces…

традиционный способ

function strStartsWith(str, prefix) {
    return str.indexOf(prefix) === 0;
}

function strEndsWith(str, suffix) {
    return str.match(suffix+"$")==suffix;
}

Вы должны сбежать из вашей строки для escape-последовательностей регулярных выражений
Хуан Мендес

1
Регулярные выражения медленны даже в быстрых языках. Просто проверьте конец строки.
Даниил Нуриев

8

Я не знаю о вас, но:

var s = "mystring#";
s.length >= 1 && s[s.length - 1] == '#'; // will do the thing!

Почему регулярные выражения? Зачем возиться с прототипом? SubStr? Да ладно...


потому что иногда лучше, когда это ВЛАЖНО
Мартин Каподичи

8

Еще одна быстрая альтернатива, которая сработала для меня как очарование с использованием регулярных выражений:

// Would be equivalent to:
// "Hello World!".endsWith("World!")
"Hello World!".match("World!$") != null


6

Я только что узнал об этой библиотеке строк:

http://stringjs.com/

Включите файл js, а затем используйте Sпеременную следующим образом:

S('hi there').endsWith('hi there')

Его также можно использовать в NodeJS, установив его:

npm install string

Затем требуя его в качестве Sпеременной:

var S = require('string');

На веб-странице также есть ссылки на библиотеки альтернативных строк, если вам не по вкусу.


4
function strEndsWith(str,suffix) {
  var reguex= new RegExp(suffix+'$');

  if (str.match(reguex)!=null)
      return true;

  return false;
}

1
Лучше, если вы объясните, почему ваш код решает проблему. Смотрите руководство Как ответить .
brasofilo

Аргумент суффикса должен быть проверен на наличие выражений регулярных выражений, которые должны быть экранированы. использование indexOf или lastIndexOf кажется лучшим вариантом.
vlad_tepesch

Это не будет работать, если суффикс содержит любой из этих символов:. * +? ^ =!: $ {} () [] / \
gtournie

4

Так много вещей для такой маленькой проблемы, просто используйте это регулярное выражение

var str = "mystring#";
var regex = /^.*#$/

if (regex.test(str)){
  //if it has a trailing '#'
}


4

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

Функции'ndsWith 'уже добавлены в JavaScript как часть ECMAScript 6 (экспериментальная технология)

См. Здесь: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith

Следовательно, настоятельно рекомендуется добавить проверку на наличие нативной реализации, как указано в ответе.


2
function check(str)
{
    var lastIndex = str.lastIndexOf('/');
    return (lastIndex != -1) && (lastIndex  == (str.length - 1));
}

2

Путь к будущему доказательству и / или предотвращению перезаписи существующего прототипа будет проверочной проверкой, чтобы увидеть, был ли он уже добавлен в прототип String. Вот мой взгляд на версию без регулярных выражений.

if (typeof String.endsWith !== 'function') {
    String.prototype.endsWith = function (suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}

Использование if (!String.prototype.hasOwnProperty("endsWith"))это лучший способ. С помощью typeof«MooTools и некоторых других библиотек AJAX вас обидят», согласно «Crockford on JavaScript - Уровень 7: ECMAScript 5: Новые части», в 15:50 мин.
XP1

2

Принятый ответ @ chakrit - это надежный способ сделать это самостоятельно. Однако, если вы ищете пакетное решение, я рекомендую взглянуть на underscore.string , как указывал @mlunoe. Используя underscore.string, код будет:

function endsWithHash(str) {
  return _.str.endsWith(str, '#');
}

1

если вы не хотите использовать lasIndexOf или substr, то почему бы просто не посмотреть на строку в ее естественном состоянии (т.е. массив)

String.prototype.endsWith = function(suffix) {
    if (this[this.length - 1] == suffix) return true;
    return false;
}

или как отдельная функция

function strEndsWith(str,suffix) {
    if (str[str.length - 1] == suffix) return true;
    return false;
}

1
String.prototype.endWith = function (a) {
    var isExp = a.constructor.name === "RegExp",
    val = this;
    if (isExp === false) {
        a = escape(a);
        val = escape(val);
    } else
        a = a.toString().replace(/(^\/)|(\/$)/g, "");
    return eval("/" + a + "$/.test(val)");
}

// example
var str = "Hello";
alert(str.endWith("lo"));
alert(str.endWith(/l(o|a)/));

1

После всех этих долгих подсчетов ответов я нашел этот кусок кода простым и легким для понимания!

function end(str, target) {
  return str.substr(-target.length) == target;
}

1

Это реализация конца с: String.prototype.endsWith = function (str) { return this.length >= str.length && this.substr(this.length - str.length) == str; }


1

Это реализация endsWith:

String.prototype.endsWith = function (str) {
  return (this.length >= str.length) && (this.substr(this.length - str.length) === str);
}

0

Это основывается на принятом ответе @ charkit, позволяющем передавать либо массив строк, либо строку в качестве аргумента.

if (typeof String.prototype.endsWith === 'undefined') {
    String.prototype.endsWith = function(suffix) {
        if (typeof suffix === 'String') {
            return this.indexOf(suffix, this.length - suffix.length) !== -1;
        }else if(suffix instanceof Array){
            return _.find(suffix, function(value){
                console.log(value, (this.indexOf(value, this.length - value.length) !== -1));
                return this.indexOf(value, this.length - value.length) !== -1;
            }, this);
        }
    };
}

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


1
Это плохое решение, скорее, если вы уже используете подчеркивание, вы должны добавить эту epeli.github.io/underscore.string к вашим зависимостям и использовать их реализацию:_.str.endsWith
mlunoe

0
if(typeof String.prototype.endsWith !== "function") {
    /**
     * String.prototype.endsWith
     * Check if given string locate at the end of current string
     * @param {string} substring substring to locate in the current string.
     * @param {number=} position end the endsWith check at that position
     * @return {boolean}
     *
     * @edition ECMA-262 6th Edition, 15.5.4.23
     */
    String.prototype.endsWith = function(substring, position) {
        substring = String(substring);

        var subLen = substring.length | 0;

        if( !subLen )return true;//Empty string

        var strLen = this.length;

        if( position === void 0 )position = strLen;
        else position = position | 0;

        if( position < 1 )return false;

        var fromIndex = (strLen < position ? strLen : position) - subLen;

        return (fromIndex >= 0 || subLen === -fromIndex)
            && (
                position === 0
                // if position not at the and of the string, we can optimise search substring
                //  by checking first symbol of substring exists in search position in current string
                || this.charCodeAt(fromIndex) === substring.charCodeAt(0)//fast false
            )
            && this.indexOf(substring, fromIndex) === fromIndex
        ;
    };
}

Льготы:

  • Эта версия не просто повторно использует indexOf.
  • Наибольшая производительность на длинных струнах. Вот тест скорости http://jsperf.com/starts-ends-with/4
  • Полностью совместим со спецификацией ecmascript. Проходит испытания

0

Не используйте регулярные выражения. Они медленные даже на быстрых языках. Просто напишите функцию, которая проверяет конец строки. Эта библиотека имеет хорошие примеры: groundjs / util.js . Будьте осторожны, добавляя функцию в String.prototype. Этот код имеет хорошие примеры того, как это сделать: groundjs / prototype.js В общем, это хорошая библиотека уровня языка: groundjs. Вы также можете взглянуть на lodash.


0

Все они очень полезные примеры. ДобавлениеString.prototype.endsWith = function(str) поможет нам просто вызвать метод, чтобы проверить, заканчивается ли наша строка этим или нет, ну и регулярное выражение также сделает это.

Я нашел лучшее решение, чем мое. Спасибо всем.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.