String.prototype.lastindexof()

SearchParams “?…”

Let’s say we want to create a url with given search params, for instance, .


We can provide them in the URL string:

…But parameters need to be encoded if they contain spaces, non-latin letters, etc (more about that below).

So there’s URL property for that: , an object of type .

It provides convenient methods for search parameters:

  • – add the parameter by ,
  • – remove the parameter by ,
  • – get the parameter by ,
  • – get all parameters with the same (that’s possible, e.g. ),
  • – check for the existence of the parameter by ,
  • – set/replace the parameter,
  • – sort parameters by name, rarely needed,
  • …and it’s also iterable, similar to .

An example with parameters that contain spaces and punctuation marks:

str.replace(str|regexp, str|func)

This is a generic method for searching and replacing, one of most useful ones. The swiss army knife for searching and replacing.

We can use it without regexps, to search and replace a substring:

There’s a pitfall though.

When the first argument of is a string, it only replaces the first match.

You can see that in the example above: only the first is replaced by .

To find all hyphens, we need to use not the string , but a regexp , with the obligatory flag:

The second argument is a replacement string. We can use special character in it:

Symbols Action in the replacement string
inserts the whole match
inserts a part of the string before the match
inserts a part of the string after the match
if is a 1-2 digit number, inserts the contents of n-th capturing group, for details see Capturing groups
inserts the contents of the parentheses with the given , for details see Capturing groups
inserts character

For instance:

For situations that require “smart” replacements, the second argument can be a function.

It will be called for each match, and the returned value will be inserted as a replacement.

The function is called with arguments :

  1. – the match,
  2. – contents of capturing groups (if there are any),
  3. – position of the match,
  4. – the source string,
  5. – an object with named groups.

If there are no parentheses in the regexp, then there are only 3 arguments: .

For example, let’s uppercase all matches:

Replace each match by its position in the string:

In the example below there are two parentheses, so the replacement function is called with 5 arguments: the first is the full match, then 2 parentheses, and after it (not used in the example) the match position and the source string:

If there are many groups, it’s convenient to use rest parameters to access them:

Or, if we’re using named groups, then object with them is always the last, so we can obtain it like this:

Using a function gives us the ultimate replacement power, because it gets all the information about the match, has access to outer variables and can do everything.

Getting a substring

There are 3 methods in JavaScript to get a substring: , and .

Returns the part of the string from to (but not including) .

For instance:

If there is no second argument, then goes till the end of the string:

Negative values for are also possible. They mean the position is counted from the string end:


Returns the part of the string between and .

This is almost the same as , but it allows to be greater than .

For instance:

Negative arguments are (unlike slice) not supported, they are treated as .

Returns the part of the string from , with the given .

In contrast with the previous methods, this one allows us to specify the instead of the ending position:

The first argument may be negative, to count from the end:

Let’s recap these methods to avoid any confusion:

method selects… negatives
from to (not including ) allows negatives
between and negative values mean
from get characters allows negative

Which one to choose?

All of them can do the job. Formally, has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.

Of the other two variants, is a little bit more flexible, it allows negative arguments and shorter to write. So, it’s enough to remember solely of these three methods.

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

regexp.test(str)

The method looks for a match and returns whether it exists.

For instance:

An example with the negative answer:

If the regexp has flag , then looks from property and updates this property, just like .

So we can use it to search from a given position:

Same global regexp tested repeatedly on different sources may fail

If we apply the same global regexp to different inputs, it may lead to wrong result, because call advances property, so the search in another string may start from non-zero position.

For instance, here we call twice on the same text, and the second time fails:

That’s exactly because is non-zero in the second test.

To work around that, we can set before each search. Or instead of calling methods on regexp, use string methods , they don’t use .

1.Using includes method in ES6:

If you are using latest versions of Javascript like ES6 you can use include method to check if a string contains a substring or not as shown below.

We will take an example and understand it further.

var substringtocheck = "includes";
var actualstring="ES6 contains includes method";
var isContains = actualstring.includes(substringtocheck);
//returns true.

includes method is case sensitive, so the below substring check returns false

var substringtocheck = "Includes";
var actualstring="ES6 contains includes method";
var isContains = actualstring.includes(substringtocheck);
// returns false

Javascript string includes method accepts two parameters

  1. substring to check
  2. search position

The second parameter search position is optional and the default value is 0.

If you want to check whether a string contains a substring only after a certain position you can pass the search position as a parameter as shown in the below examples.

var substringtocheck = "ES6";
var actualstring="ES6 contains includes method";
var isContains = actualstring.includes(substringtocheck,1);
//returns false. As we are checking for ES6 substring after position 1.

includes method is very easy to use and comes with additional options like search position.

In older versions of Javascript, we can add a polyfill for include method

if (!String.prototype.includes) {

Object.defineProperty(String.prototype, 'includes', {
  value: function(substring, searchposition) {
     if (typeof searchposition!== 'number') {
       searchposition= 0
     }
     if (searchposition+ substring.length > this.length) {
       return false
     } else {
       return this.indexOf(substring, searchposition) !== -1
     }
  }
})
}

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

Encoding


There’s a standard RFC3986 that defines which characters are allowed in URLs and which are not.

Those that are not allowed, must be encoded, for instance non-latin letters and spaces – replaced with their UTF-8 codes, prefixed by , such as (a space can be encoded by , for historical reasons, but that’s an exception).

The good news is that objects handle all that automatically. We just supply all parameters unencoded, and then convert the to string:

As you can see, both in the url path and in the parameter are encoded.

The URL became longer, because each cyrillic letter is represented with two bytes in UTF-8, so there are two entities.

In old times, before objects appeared, people used strings for URLs.

As of now, objects are often more convenient, but strings can still be used as well. In many cases using a string makes the code shorter.

If we use a string though, we need to encode/decode special characters manually.

There are built-in functions for that:

  • encodeURI – encodes URL as a whole.
  • decodeURI – decodes it back.
  • encodeURIComponent – encodes a URL component, such as a search parameter, or a hash, or a pathname.
  • decodeURIComponent – decodes it back.

A natural question is: “What’s the difference between and ? When we should use either?”

That’s easy to understand if we look at the URL, that’s split into components in the picture above:

As we can see, characters such as , , , , are allowed in URL.

…On the other hand, if we look at a single URL component, such as a search parameter, these characters must be encoded, not to break the formatting.

  • encodes only characters that are totally forbidden in URL.
  • encodes same characters, and, in addition to them, characters , , , , , , , , , and .

So, for a whole URL we can use :

…While for URL parameters we should use instead:

Compare it with :

As we can see, does not encode , as this is a legit character in URL as a whole.

But we should encode inside a search parameter, otherwise, we get – that is actually plus some obscure parameter . Not as intended.

So we should use only for each search parameter, to correctly insert it in the URL string. The safest is to encode both name and value, unless we’re absolutely sure that it has only allowed characters.

Encoding difference compared to

Classes and are based on the latest URI specification: RFC3986, while functions are based on the obsolete version RFC2396.

There are few differences, e.g. IPv6 addresses are encoded differently:

As we can see, replaced square brackets , that’s not correct, the reason is: IPv6 urls did not exist at the time of RFC2396 (August 1998).

Such cases are rare, functions work well most of the time.

Internals, Unicode

Advanced knowledge

The section goes deeper into string internals. This knowledge will be useful for you if you plan to deal with emoji, rare mathematical or hieroglyphic characters or other rare symbols.

You can skip the section if you don’t plan to support them.

All frequently used characters have 2-byte codes. Letters in most european languages, numbers, and even most hieroglyphs, have a 2-byte representation.

But 2 bytes only allow 65536 combinations and that’s not enough for every possible symbol. So rare symbols are encoded with a pair of 2-byte characters called “a surrogate pair”.


The length of such symbols is :

Note that surrogate pairs did not exist at the time when JavaScript was created, and thus are not correctly processed by the language!

We actually have a single symbol in each of the strings above, but the shows a length of .

and are few rare methods that deal with surrogate pairs right. They recently appeared in the language. Before them, there were only String.fromCharCode and str.charCodeAt. These methods are actually the same as , but don’t work with surrogate pairs.

Getting a symbol can be tricky, because surrogate pairs are treated as two characters:

Note that pieces of the surrogate pair have no meaning without each other. So the alerts in the example above actually display garbage.

Technically, surrogate pairs are also detectable by their codes: if a character has the code in the interval of , then it is the first part of the surrogate pair. The next character (second part) must have the code in interval . These intervals are reserved exclusively for surrogate pairs by the standard.

In the case above:

You will find more ways to deal with surrogate pairs later in the chapter Iterables. There are probably special libraries for that too, but nothing famous enough to suggest here.

In many languages there are symbols that are composed of the base character with a mark above/under it.

For instance, the letter can be the base character for: . Most common “composite” character have their own code in the UTF-16 table. But not all of them, because there are too many possible combinations.

To support arbitrary compositions, UTF-16 allows us to use several unicode characters: the base character followed by one or many “mark” characters that “decorate” it.

For instance, if we have followed by the special “dot above” character (code ), it is shown as Ṡ.

If we need an additional mark above the letter (or below it) – no problem, just add the necessary mark character.

For instance, if we append a character “dot below” (code ), then we’ll have “S with dots above and below”: .

For example:

This provides great flexibility, but also an interesting problem: two characters may visually look the same, but be represented with different unicode compositions.

For instance:

To solve this, there exists a “unicode normalization” algorithm that brings each string to the single “normal” form.

It is implemented by str.normalize().

It’s funny that in our situation actually brings together a sequence of 3 characters to one: (S with two dots).

In reality, this is not always the case. The reason being that the symbol is “common enough”, so UTF-16 creators included it in the main table and gave it the code.

If you want to learn more about normalization rules and variants – they are described in the appendix of the Unicode standard: Unicode Normalization Forms, but for most practical purposes the information from this section is enough.

JavaScript

JS Array concat() constructor copyWithin() entries() every() fill() filter() find() findIndex() forEach() from() includes() indexOf() isArray() join() keys() length lastIndexOf() map() pop() prototype push() reduce() reduceRight() reverse() shift() slice() some() sort() splice() toString() unshift() valueOf()

JS Boolean constructor prototype toString() valueOf()

JS Classes constructor() extends static super

JS Date constructor getDate() getDay() getFullYear() getHours() getMilliseconds() getMinutes() getMonth() getSeconds() getTime() getTimezoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHours() getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() now() parse() prototype setDate() setFullYear() setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTime() setUTCDate() setUTCFullYear() setUTCHours() setUTCMilliseconds() setUTCMinutes() setUTCMonth() setUTCSeconds() toDateString() toISOString() toJSON() toLocaleDateString() toLocaleTimeString() toLocaleString() toString() toTimeString() toUTCString() UTC() valueOf()

JS Error name message

JS Global decodeURI() decodeURIComponent() encodeURI() encodeURIComponent() escape() eval() Infinity isFinite() isNaN() NaN Number() parseFloat() parseInt() String() undefined unescape()

JS JSON parse() stringify()

JS Math abs() acos() acosh() asin() asinh() atan() atan2() atanh() cbrt() ceil() cos() cosh() E exp() floor() LN2 LN10 log() LOG2E LOG10E max() min() PI pow() random() round() sin() sqrt() SQRT1_2 SQRT2 tan() tanh() trunc()

JS Number constructor isFinite() isInteger() isNaN() isSafeInteger() MAX_VALUE MIN_VALUE NEGATIVE_INFINITY NaN POSITIVE_INFINITY prototype toExponential() toFixed() toLocaleString() toPrecision() toString() valueOf()

JS OperatorsJS RegExp constructor compile() exec() g global i ignoreCase lastIndex m multiline n+ n* n? n{X} n{X,Y} n{X,} n$ ^n ?=n ?!n source test() toString() (x|y) . \w \W \d \D \s \S \b \B \0 \n \f \r \t \v \xxx \xdd \uxxxx

JS Statements break class continue debugger do…while for for…in for…of function if…else return switch throw try…catch var while

JS String charAt() charCodeAt() concat() constructor endsWith() fromCharCode() includes() indexOf() lastIndexOf() length localeCompare() match() prototype repeat() replace() search() slice() split() startsWith() substr() substring() toLocaleLowerCase() toLocaleUpperCase() toLowerCase() toString() toUpperCase() trim() valueOf()

2.In ES5 and before using indexOf method

In ES5 and before versions of Javascript we can use indexOf method to check if a string contains a substring or not.

Go through the following code example to understand it further.

var actualstring = "In ES5 use IndexOf method",
var substringToCheck = "IndexOf";
var isContains=actualstring.indexOf(substringToCheck) !== -1;
//isContains true

The indexOf method will return the substring position if it found, otherwise returns -1.

And indexOf method is case sensitive,accepts two parameter similar to includes method.

var actualstring = "In ES5 use IndexOf method",
var substringToCheck = "indexOf";
var isContains=actualstring.indexOf(substringToCheck) !== -1;
//isContains false as
var isContainsAfterPosition = actualstring.indexOf("In",2) !== -1;
//false.

We can simply add pollyfil method for includes as it uses indexOf method internally.


С этим читают