закінчується в JavaScript


1103

Як я можу перевірити, чи рядок закінчується певним символом у JavaScript?

Приклад: У мене є рядок

var str = "mystring#";

Я хочу знати, чи закінчується цей рядок #. Як я можу це перевірити?

  1. Чи існує endsWith()метод у JavaScript?

  2. Одне з моїх рішень - взяти довжину рядка і отримати останній символ і перевірити його.

Це найкращий спосіб чи є інший спосіб?


5
Це повинен бути пов'язаний питання: stackoverflow.com/questions/646628/javascript-startswith
Хеміш Grubijan

Відповіді:


1764

ОНОВЛЕННЯ (24 листопада 2015 р.):

Ця відповідь спочатку розміщена у 2010 році (SIX років тому), тому, будь ласка, врахуйте ці проникливі коментарі:

  • Shauna - оновлення для Googlers - схоже, ECMA6 додає цю функцію. У статті MDN також показаний полів. 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 додає кінціWith, то справа суперечлива. :-)


ОРИГІНАЛЬНИЙ ВІДПОВІДЬ:

Я знаю, що це питання за рік ... але мені це теж потрібно, і мені потрібно, щоб він працював крос-браузером, так що поєднуючи відповіді та коментарі кожного та трохи спростивши його:

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;
}

EDIT: Як зазначає @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 також показаний полів. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Shauna

2
@ lukas.pukenis він пропускає до кінця і перевіряє лише один екземпляр суфікса в самому кінці. не має значення, якщо рядок пошуку з’являється в іншому місці.
чакрит

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

2
Про які ускладнення регексу ви згадали?
IcedDante

5
Створення підрядів не є дорогим для сучасних браузерів; можливо, це було в 2010 році, коли ця відповідь була розміщена. На сьогоднішній день простий this.substr(-suffix.length) === suffixпідхід найшвидший на Chrome, той самий на IE11 як indexOfі лише на 4% повільніше (територія fergetaboutit) у Firefox: jsperf.com/endswith-stackoverflow/14 І швидше за все, коли результат хибний: jsperf .com / endwith-stackoverflow-when-false Звичайно, з додаванням 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
@Tom Brito, це регулярний вираз у прямому сенсі. Синтаксис запозичений з Perl. Див. Developer.mozilla.org/en/Core_JavaScript_1.5_Guide/… або про непотрібний рівень деталізації, див розділ 7.8.5 специфікації мови EcmaScript.
Майк Самуель

2
+1 для сумісності між веб-переглядачами. Тестовано на Chrome 28.0.1500.72 м, Firefox 22.0 та IE9.
Адрієн Бе

91
  1. На жаль ні.
  2. if( "mystring#".substr(-1) === "#" ) {}

14
@Anthony, гм ... так що використовуйте .Length-1, в чому проблема? якщо (mystring.substr (mystring.length-1) === "#") {} в IE працює чудово.
BrainSlugs83

12
@ BrainSlugs83 - саме в цьому проблема: синтаксис '.length-1' працює в IE, а синтаксис '-1' не працює. Це потрібно пам’ятати, тому +1 до Ентоні за пораду.
avramov

2
Ви не можете скористатися slice()? Це працює для мене в моєму швидкому тесті IE7.
алекс

відляканий 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», який згадав чакрит, а в Safari - на 30% повільніше! Ось тест jsPerf на випадок відмови приблизно в 50-символьному рядку: jsperf.com/endswithcomparison
Brent Faust

4
Напевно, слід використовувати, ===хоча.
Timmmm

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, ви можете вражати випадки, коли він повертає справжнє залежність від this.length та str.length. Додайте тест, що lastIndexOf ()! = -1.
ebruchez

1
Чому метод регексу порушений?
izb

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

26

Не бачив відповідності з sliceметодом. Тож я просто залишаю його тут:

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

1
Ви можете трохи спростити це: return str.slice (-1) === суфікс;
Ерік К.

2
Це найкраща відповідь. Не впевнений, чому в ньому немає більше подій.
ядерніт

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

не працює в тому випадку, коли початкова довжина рядка на одну меншу довжини рядка пошуку і рядок пошуку не знайдено:

lastIndexOf повертає -1, тоді ви додаєте довжину рядка пошуку і вам залишається початкова довжина рядка.

Можливе виправлення

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

30
Ви заробили значок "Знайшов помилку у відповіді Джона Скіта". Детальніше див. У своєму профілі.
bobince

17

Від developer.mozilla.org String.prototype.endsWith ()

Підсумок

endsWith()Метод визначає , є чи рядок закінчується символами іншого рядка, повертаючи істинним або хибним залежно від обставин.

Синтаксис

str.endsWith(searchString [, position]);

Параметри

  • searchString : символи, які потрібно шукати в кінці цього рядка.

  • позиція : шукайте всередині цього рядка так, ніби ця строка була лише такою довгою; за замовчуванням до фактичної довжини цього рядка, затиснутого в межах, встановлених довжиною цього рядка.

Опис

Цей метод дозволяє визначити, закінчується чи ні рядок іншою рядком.

Приклади

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

Технічні умови

6-е видання специфікації мови ECMAScript (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;
}

Вам потрібно уникнути рядка для послідовностей втечі від регулярних виразів
Хуан Мендес

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

8

Я не знаю про тебе, але:

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

Чому регулярні вирази? Чому возитися з прототипом? substr? давай ...


Тому що іноді краще, коли це WET
Martin Capodici

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

Минуло багато років на це питання. Дозвольте додати важливе оновлення для користувачів, які хочуть використати відповідь на найбільш голосовані чакрити.

Функції 'endWith' вже додані до 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 - Level 7: ECMAScript 5: The New Parts", о 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

Це реалізація цілейWith: 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)допоможе нам просто викликати метод, щоб перевірити, чи закінчується наша рядок на цьому чи ні, також regexp також зробить це.

Я знайшов краще рішення, ніж моє. Дякую всім.


0

Для кофескрипту

String::endsWith = (suffix) ->
  -1 != @indexOf suffix, @length - suffix.length
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.