Array及String的lastIndexOf函数用法及其IE8实现,及为什么要尽量避免使用for in


发布者 kris  发布时间 1454642901926
关键字 JS学习  JavaScript 
Array.prototype.lastIndexOf 和 String.prototype.lastIndexOf 是非常的实用一个函数,不过很多人不知道它其实可以传递两个参数,第二个参数决定了搜索的起始位置:

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

同样 String.lastIndexOf的用法类似

"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

lastIndexOf的IE8实现


不过微软的IE8及其以下并不支持Array.lastIndexOf,需要兼容实现。可以参考:

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

可以使用 ES5-Slim 使旧版浏览器完全兼容ES5语法。

为什么要避免使用for in


不过要注意的是,在Array.prototype上面附加方法后,for in语法也会把lastIndexOf方法也枚举出来:

for (var idx in [1,3,5,7,9]) {
  console.log(idx)
} >> 0 1 2 3 4 lastIndexOf

而应该使用 for loop实现

for (var idx = 0; idx < [1,3,5,7,9].length; idx++) {
  console.log(idx)
}

这个问题可以使用 Object.defineProperty 来实现,来避免for in的枚举出lastIndexOf方法: 

Object.defineProperty(Array, "lastIndexOf", { enumerable: false })

不过一般需要兼容实现的浏览器根本不支持defineProperty 方法。并且在多数浏览器上for in都比for loop要慢很多,因此应该尽量避免使用for in。但是如何枚举Object属性的key呢? 使用Object.keys({ a:1 })即可返回关于keys的数组。


相关: 
for in 比for loop慢至少20倍



参考: 
https://msdn.microsoft.com/library/ff679972(v=vs.94).aspx
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/lastIndexOf