termina con JavaScript

1103

¿Cómo puedo verificar si una cadena termina con un carácter particular en JavaScript?

Ejemplo: tengo una cadena

var str = "mystring#";

Quiero saber si esa cadena termina con #. ¿Cómo puedo verificarlo?

  1. ¿Hay algún endsWith()método en JavaScript?

  2. Una solución que tengo es tomar la longitud de la cadena y obtener el último carácter y verificarlo.

¿Es esta la mejor manera o hay alguna otra?

Bobby Kumar
fuente
55
Esto tiene que ser una pregunta relacionada: stackoverflow.com/questions/646628/javascript-startswith
Hamish Grubijan

Respuestas:

1764

ACTUALIZACIÓN (24 de noviembre de 2015):

Esta respuesta se publicó originalmente en el año 2010 (SEIS años atrás), así que tome nota de estos comentarios perspicaces:


RESPUESTA ORIGINAL:

Sé que esta es una pregunta de hace un año ... pero también la necesito y la necesito para funcionar en varios navegadores, así que ... combinando las respuestas y comentarios de todos y simplificándola un poco:

String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
  • No crea una subcadena
  • Utiliza la indexOffunción nativa para obtener resultados más rápidos.
  • Omita las comparaciones innecesarias utilizando el segundo parámetro de indexOfpara saltar adelante
  • Funciona en Internet Explorer
  • NO complicaciones Regex

Además, si no le gusta rellenar cosas en los prototipos de la estructura de datos nativa, aquí hay una versión independiente:

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

EDITAR: como señaló @hamish en los comentarios, si desea errar en el lado seguro y verificar si ya se ha proporcionado una implementación, simplemente puede agregar una typeofverificación de esta manera:

if (typeof String.prototype.endsWith !== 'function') {
    String.prototype.endsWith = function(suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}
chakrit
fuente
42
Actualización para Googlers: parece que ECMA6 agrega esta función. El artículo de MDN también muestra un polyfill. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Shauna
2
@ lukas.pukenis salta hasta el final y solo verifica una instancia del sufijo al final. no importa si la cadena de búsqueda aparece en otro lugar.
chakrit
3
Agregar una comprobación de la situación cuando el argumento "sufijo" no está definido ": if (typeof String.prototype.endsWith! == 'function') {String.prototype.endsWith = function (sufijo) {return this.indexOf (sufijo , this.length - ((sufijo && sufijo.length) || 0))! == -1;};}
Mandeep
2
¿Cuáles son las complicaciones de expresiones regulares a las que se refirió?
IcedDante
55
Crear subcadenas no es costoso en los navegadores modernos; bien pudo haber sido en 2010 cuando se publicó esta respuesta. En estos días, el this.substr(-suffix.length) === suffixenfoque simple es más rápido en Chrome, el mismo en IE11 que indexOf, y solo un 4% más lento (fergetaboutit territorio) en Firefox: jsperf.com/endswith-stackoverflow/14 Y más rápido en todos los ámbitos cuando el resultado es falso: jsperf .com / endswith-stackoverflow-when-false Por supuesto, con ES6 agregando endsWith, el punto es discutible. :-)
TJ Crowder
295
/#$/.test(str)

funcionará en todos los navegadores, no requiere parches de mono Stringy no requiere escanear toda la cadena como lo lastIndexOfhace cuando no hay coincidencia

Si desea hacer coincidir una cadena constante que puede contener caracteres especiales de expresión regular, como '$', puede usar lo siguiente:

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

y luego puedes usarlo así

makeSuffixRegExp("a[complicated]*suffix*").test(str)
Mike Samuel
fuente
10
Esto es agradable y simple si está buscando una subcadena constante.
Warren Blanchet
1
lastIndexOf escanea toda la cadena? Pensé que buscaría desde el final hasta el principio.
Tom Brito
3
@TomBrito, lastIndexOfescanea toda la cadena solo si no encuentra una coincidencia o si encuentra una coincidencia al principio. Si hay una coincidencia al final, entonces funciona proporcionalmente a la longitud del sufijo. Sí, /asdf$/.test(str)produce verdadero cuando strtermina con "asdf".
Mike Samuel
3
@ Tom Brito, es una expresión regular literal. La sintaxis es prestada de Perl. Consulte developer.mozilla.org/en/Core_JavaScript_1.5_Guide/… o para obtener un nivel de detalle innecesario, consulte la sección 7.8.5 de la especificación del lenguaje EcmaScript.
Mike Samuel
2
+1 para la compatibilidad entre navegadores. Probado en Chrome 28.0.1500.72 m, Firefox 22.0 e IE9.
Adrien Be
91
  1. Lamentablemente no.
  2. if( "mystring#".substr(-1) === "#" ) {}
Phillip B Oldham
fuente
14
@ Anthony, um ... así que usa .Longitud-1, ¿cuál es el problema? if (mystring.substr (mystring.length-1) === "#") {} funciona bien en IE.
BrainSlugs83
12
@ BrainSlugs83: ese es exactamente el problema: la sintaxis '.length-1' funciona en IE y la sintaxis '-1' no. Es algo a tener en cuenta, así que +1 a Anthony por el consejo.
avramov
2
¿No podrías usar slice()? Funciona para mí en mi prueba rápida de IE7.
alex
Freaken IE. cuando va a morir?
ahnbizcad
67

Vamos, esta es la endsWithimplementación correcta :

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

el uso lastIndexOfsolo crea bucles de CPU innecesarios si no hay coincidencia.

Oskar Liljeblad
fuente
2
Convenido. Realmente siento que esta es la solución más eficiente que se ofrece, ya que tiene un aborto temprano / verificación de cordura, es breve y conciso, es elegante (sobrecargando el prototipo de cadena) y la subcadena parece ser un golpe de recursos mucho menor que poner en marcha el motor de expresiones regulares.
BrainSlugs83
También me gusta esta solución. Solo el nombre de la función está mal escrito. Debe ser "termina con".
xmedeko
3
@ BrainSlugs83 Han pasado un par de años, pero ahora este método no es más rápido que el método 'indexOf' mencionado anteriormente por chakrit, y bajo Safari, ¡es un 30% más lento! Aquí hay una prueba jsPerf para el caso de falla sobre una cadena de 50 caracteres: jsperf.com/endswithcomparison
Brent Faust
44
Probablemente debería usar ===sin embargo.
Timmmm
56

Esta versión evita crear una subcadena y no usa expresiones regulares (algunas respuestas de expresiones regulares funcionarán aquí; otras están rotas):

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

Si el rendimiento es importante para usted, valdría la pena probar si lastIndexOfes realmente más rápido que crear una subcadena o no. (Puede depender del motor JS que esté usando ...) Puede ser más rápido en el caso de coincidencia, y cuando la cadena es pequeña, pero cuando la cadena es enorme, necesita mirar hacia atrás incluso aunque realmente no nos importa :(

Para verificar un solo carácter, encontrar la longitud y luego usarlo charAtes probablemente la mejor manera.

Jon Skeet
fuente
2
Si this.lastIndexOf () devuelve -1, puede encontrar casos en los que devuelve verdadero dependiendo de this.length y str.length. Agregue una prueba que lastIndexOf ()! = -1.
ebruchez
1
¿Por qué se rompe el método regex?
izb
2
@izb: Las respuestas que son más antiguas que las mías que intentan usar str+"$"como expresiones regulares están rotas, ya que pueden no ser expresiones regulares válidas.
Jon Skeet
26

No vi apporach con slicemétodo. Así que solo lo dejo aquí:

function endsWith(str, suffix) {
    return str.slice(-suffix.length) === suffix
}
Nikita Koksharov
fuente
1
Puede simplificarlo un poco más: return str.slice (-1) === sufijo;
Erik K.
2
Esta es la mejor respuesta. No estoy seguro de por qué no tiene más votos a favor.
nucleartide
17
return this.lastIndexOf(str) + str.length == this.length;

no funciona en el caso de que la longitud de la cadena original sea uno menos que la longitud de la cadena de búsqueda y no se encuentre la cadena de búsqueda:

lastIndexOf devuelve -1, luego agrega la longitud de la cadena de búsqueda y queda la longitud de la cadena original.

Una posible solución es

return this.length >= str.length && this.lastIndexOf(str) + str.length == this.length
usuario73745
fuente
30
Te has ganado la insignia "Encontró un error en una respuesta de Jon Skeet". Vea su perfil para más detalles.
bobince
17

De developer.mozilla.org String.prototype.endsWith ()

Resumen

El endsWith()método determina si una cadena termina con los caracteres de otra cadena, devolviendo verdadero o falso según corresponda.

Sintaxis

str.endsWith(searchString [, position]);

Parámetros

  • searchString : los caracteres que se buscarán al final de esta cadena.

  • position : busca dentro de esta cadena como si esta cadena fuera tan larga; el valor predeterminado es la longitud real de esta cadena, sujeta dentro del rango establecido por la longitud de esta cadena.

Descripción

Este método le permite determinar si una cadena termina o no con otra cadena.

Ejemplos

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

Especificaciones

Especificación del lenguaje ECMAScript 6ta edición (ECMA-262)

Compatibilidad del navegador

Compatibilidad del navegador

Aniket Kulkarni
fuente
10
if( ("mystring#").substr(-1,1) == '#' )

O bien

if( ("mystring#").match(/#$/) )
duckyflip
fuente
8
String.prototype.endsWith = function(str) 
{return (this.match(str+"$")==str)}

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

espero que esto ayude

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…

la forma tradicional

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

function strEndsWith(str, suffix) {
    return str.match(suffix+"$")==suffix;
}
Mohammed Rafeeq
fuente
Tienes que escapar de tu cadena para las secuencias de escape de expresiones regulares
Juan Mendes
1
Las expresiones regulares son lentas incluso en lenguajes rápidos. Solo verifique el final de una cadena.
Daniel Nuriyev
8

No sé sobre ti, pero:

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

¿Por qué expresiones regulares? ¿Por qué jugar con el prototipo? substr? vamos...

Tici
fuente
porque a veces es mejor cuando está
MOJADO
8

Solo otra alternativa rápida que funcionó de maravilla para mí, usando regex:

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

Si estás usando lodash :

_.endsWith('abc', 'c'); // true

Si no usa lodash, puede tomar prestado de su fuente .

Dheeraj Vepakomma
fuente
6

Acabo de enterarme de esta biblioteca de cadenas:

http://stringjs.com/

Incluya el archivo js y luego use la Svariable como esta:

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

También se puede usar en NodeJS instalándolo:

npm install string

Luego requiriéndolo como la Svariable:

var S = require('string');

La página web también tiene enlaces a bibliotecas de cadenas alternativas, si esta no te gusta.

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

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

  return false;
}
Tabish Usman
fuente
1
Es mejor si explica por qué su código resuelve el problema. Consulte la guía Cómo responder .
brasofilo
el argumento del sufijo debe analizarse en busca de expresiones de expresión regular que deben escaparse. Usar indexOf o lastIndexOf parece ser una mejor opción.
vlad_tepesch
No funcionará si el sufijo contiene alguno de estos caracteres:. * +? ^ =!: $ {} () [] / \
gtournie
4

Tantas cosas para un problema tan pequeño, solo use esta expresión regular

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

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

LahiruBandara
fuente
4

Han pasado muchos años para esta pregunta. Permítanme agregar una actualización importante para los usuarios que desean usar la respuesta de chakrit más votada.

Las funciones 'endsWith' ya están agregadas a JavaScript como parte de ECMAScript 6 (tecnología experimental)

Consulte aquí: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith

Por lo tanto, se recomienda agregar una verificación de la existencia de una implementación nativa como se menciona en la respuesta.

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

Una forma de probar en el futuro y / o evitar la sobrescritura del prototipo existente sería la comprobación de prueba para ver si ya se ha agregado al prototipo de cadena. Aquí está mi opinión sobre la versión de alta calificación no regex.

if (typeof String.endsWith !== 'function') {
    String.prototype.endsWith = function (suffix) {
        return this.indexOf(suffix, this.length - suffix.length) !== -1;
    };
}
Dan Doyon
fuente
Usar if (!String.prototype.hasOwnProperty("endsWith"))es la mejor manera. Con typeof"MooTools y algunas de las otras bibliotecas AJAX lo arruinarán", según "Crockford en JavaScript - Nivel 7: ECMAScript 5: Las nuevas partes", a las 15:50 min.
XP1
2

La respuesta aceptada de @ chakrit es una forma sólida de hacerlo usted mismo. Sin embargo, si está buscando una solución empaquetada, le recomiendo echar un vistazo a underscore.string , como señaló @mlunoe. Usando underscore.string, el código sería:

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

si no desea utilizar lasIndexOf o substr, ¿por qué no mirar la cadena en su estado natural (es decir, una matriz)?

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

o como una función independiente

function strEndsWith(str,suffix) {
    if (str[str.length - 1] == suffix) return true;
    return false;
}
usuario511941
fuente
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)/));
Ebubekir Dirican
fuente
1

Después de toda esa larga lista de respuestas, ¡encontré este código simple y fácil de entender!

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

Esta es la implementación de fines con: String.prototype.endsWith = function (str) { return this.length >= str.length && this.substr(this.length - str.length) == str; }

Singh123
fuente
1

Esta es la implementación de endsWith:

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

Esto se basa en la respuesta aceptada de @ charkit que permite una matriz de cadenas o una cadena para pasar como argumento.

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

Esto requiere guiones bajos, pero probablemente se pueda ajustar para eliminar la dependencia de guiones bajos.

Matthew Brown
fuente
1
Esta es una mala solución, más bien si ya está usando guión bajo, debe agregar este epeli.github.io/underscore.string a sus dependencias y usar su implementación:_.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
        ;
    };
}

Beneficios:

  • Esta versión no solo está reutilizando indexOf.
  • Mayor rendimiento en cuerdas largas. Aquí hay una prueba de velocidad http://jsperf.com/starts-ends-with/4
  • Totalmente compatible con la especificación ecmascript. Pasa las pruebas
termi
fuente
0

No uses expresiones regulares. Son lentos incluso en idiomas rápidos. Simplemente escriba una función que verifique el final de una cadena. Esta biblioteca tiene buenos ejemplos: groundjs / util.js . Tenga cuidado al agregar una función a String.prototype. Este código tiene buenos ejemplos de cómo hacerlo: groundjs / prototype.js En general, esta es una buena biblioteca de nivel de lenguaje: groundjs También puedes echar un vistazo a lodash

Daniel Nuriyev
fuente
0

Todos ellos son ejemplos muy útiles. AgregandoString.prototype.endsWith = function(str) nos ayudará a simplemente llamar al método para verificar si nuestra cadena termina con él o no, bueno, regexp también lo hará.

Encontré una solución mejor que la mía. Gracias a todos.

Bobby Kumar
fuente
0

Para coffeescript

String::endsWith = (suffix) ->
  -1 != @indexOf suffix, @length - suffix.length
Quanlong
fuente