Array.prototype.lastIndexOf and String.prototype.lastIndexOf are very practical methods, but many people don’t know that they can actually pass two parameters. The second parameter determines the starting position of the search:
Grammar
str.lastIndexOf(searchValue[, fromIndex])
The lastIndexOf() method returns the last occurrence of the specified value in the string that calls this method, or -1 if not found. Search forward from the end of the string, starting from fromIndex.
Parameters
1.searchValue
A string representing the value to be found.
2.fromIndex
Begin the search at the position in the string where the method was called. Can be any integer. The default value is str.length. If negative, it is treated as 0. If fromIndex > str.length, then fromIndex is treated as str.length.
Case sensitive
lastIndexOf method is case sensitive. For example, the following expression returns -1:
"Blue Whale, Killer Whale".lastIndexOf("blue"); // returns -1
Usage of lastIndexOf
// Create an array. var ar = ["ab", "cd", "ef", "ab", "cd"]; // 找到最后一个CD的位置 document.write(ar.lastIndexOf("cd") + "<br/>"); // 输出: 4 // 从正数第二个位置,搜索倒数第一个CD的位置 document.write(ar.lastIndexOf("cd", 2) + "<br/>"); // 输出: 1 // 从倒数第三个搜索最后一个ab的位置 document.write(ar.lastIndexOf("ab", -3) + "<br/>"); // 输出: 0
Same usage of String.lastIndexOf is similar
"canal".lastIndexOf("a") // returns 3 "canal".lastIndexOf("a",2) // returns 1 "canal".lastIndexOf("a",0) // returns -1 从第0个往前搜,不存在'a',返回-1 "canal".lastIndexOf("x") // returns -1
IE8 implementation of lastIndexOf
However, Microsoft's IE8 and below do not support Array.lastIndexOf, and a compatible implementation is required. You can refer to:
if (!Array.prototype.lastIndexOf) { Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/) { 'use strict'; if (this === void 0 || this === null) { throw new TypeError(); } var n, k, t = Object(this), len = t.length >>> 0; if (len === 0) { return -1; } n = len - 1; if (arguments.length > 1) { n = Number(arguments[1]); if (n != n) { n = 0; } else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) { n = (n > 0 || -1) * Math.floor(Math.abs(n)); } } for (k = n >= 0 ? Math.min(n, len - 1) : len - Math.abs(n); k >= 0; k--) { if (k in t && t[k] === searchElement) { return k; } } return -1; }; }
You can use ES5-Slim to make older browsers fully compatible with ES5 syntax.
Why you should avoid using for in
However, it should be noted that after adding methods to Array.prototype, the for in syntax will also enumerate the lastIndexOf method:
for (var idx in [1,3,5,7,9]) { console.log(idx) } >> 0 1 2 3 4 lastIndexOf
You should use for loop instead
for (var idx = 0; idx < [1,3,5,7,9].length; idx++) { console.log(idx) }
This problem can be implemented using Object.defineProperty to avoid the lastIndexOf method of for in enumeration:
Object.defineProperty(Array, "lastIndexOf", { enumerable: false })
However, browsers that generally require compatible implementations do not support the defineProperty method at all. And in most browsers, for in is much slower than for loop, so you should try to avoid using for in. But how to enumerate the keys of Object properties? Use Object.keys({ a:1 }) to return an array of keys.