探索并手动封装ES5数组新增方法-indexOf和lastIndexOf

2,073 阅读3分钟

前言

之前我封装过ES3数组的核心方法,但后来有新的版本ES5、ES6。一个版本的跟新迭代必然会摈弃一些旧的东西,同时新增一些实用的东西。这次我们一起来看ES5中数组的新增方法并实现封装

新增方法

首先,我们将这些方法归类:

  • 2个索引方法:indexOf() 和 lastIndexOf()
  • 5个迭代方法:forEach()、map()、filter()、some()、every()
  • 2个归并方法:reduce()、reduceRight()

这里我们先来看前面两个方法的模拟实现

indexOf()和lastIndexOf()

这两个方法都是用于返回元素在数组中第一次被查找到的索引位置,如果没有找到,那么返回-1。 都接收两个参数:

  1. 第一个参数是要查找的东西
  2. 第二个参数是查找起点位置的索引,如果缺省或是格式不正确,那么默认为0。第二个参数可选

区别就是一个从前往后找,一个从后往前找

基本使用

一起来看例子,先定义一个数组:

var arr = [1, 2, 3, 4, 5, 6];

indexOf():从数组的开头开始向后查找。

console.log(arr.indexOf(3));//2   只传一个值,默认从第0项开始查找  知道返回索引
console.log(arr.indexOf(10));//-1 没找到返回-1
console.log(arr.indexOf());//-1   什么都不传,返回-1
console.log(arr.indexOf(3,'a'));//2   传两个值,第二个格式不正确,默认从第0项开始查找
console.log(arr.indexOf(3,2));//2   从第2项开始查找,返回找到位置

lastIndexOf(): 从数组的末尾开始向前查找。

console.log(arr.lastIndexOf(3));//2    值传一个值,表示从倒数第一位开始查找,找到返回索引
console.log(arr.lastIndexOf(7));//-1  没找到返回-1
console.log(arr.lastIndexOf());//-1   什么都不传,返回-1
console.log(arr.lastIndexOf(3,'a'));//-1   
console.log(arr.lastIndexOf(1,'a'));//0   传两个值,第二个格式不正确,默认从倒数最后一位开始查找,即只是找一位
console.log(arr.lastIndexOf(3,2));//2   第二位是正常数值,从该位置开始向前查找,没有找到返回-1  

观察发现除了一个从前往后找,一个从后往前找的区别外,我们还发现一个小区别,就是当第二个参数错误时,都是默认从0位开始查找,导致indexOf()查找整个数组,lastIndexOf只查找第0位。

查找对比时,会使用全等操作符"===", 要求必须完全相等,否则返回-1。

console.log(arr.indexOf('1'))//-1   这里"1"和1是不相等

另外第二个参数也不存在隐式类型转换

console.log(arr.lastIndexOf(3,'1'));//-1 

模拟封装_indexOf

Array.prototype._indexOf = function (val, start) {
  var self = this;
  if (arguments.length == 0) {
    return -1;
  }
  if (arguments.length == 1) {
    return _searchFromZero();
  }
  if (arguments.length >= 2) {
    // 这里得处理第二个参数:接受负值的情况 和 接受错误值的情况(判断是不是数字)
    if (typeof start !== "number" || isNaN(start)) {
      return _searchFromZero();
    }
    //否则就是数字,数字分正数和负数,负数可以通过运算转成正数
    if (typeof start === "number" && !isNaN(start)) {
      start = start >= 0 ? start : start + this.length;
      var temp = 0;
      for (var i = start; i < this.length; i++) {
        temp++;
        if (this[i] === val) {
          return start + temp - 1;//变成下标
        }
      }
      return -1;
    }
  }
  function _searchFromZero() {
    for (var i = 0; i < self.length; i++) {
      if (self[i] === val) {
        return i;
      }
    }
    return -1;
  }
}

测试

// test code
console.log(arr._indexOf(3));//2   只传一个值,默认从第0项开始查找
console.log(arr._indexOf(7));//-1 没找到返回-1
console.log(arr._indexOf());//-1   什么都不传,返回-1
console.log(arr._indexOf(3, 'a'));//2   第二个格式不正确,从第0项开始查找
console.log(arr._indexOf(3, 0));//2   
console.log(arr._indexOf(3, -4));//2   
console.log(arr._indexOf(3, -5));//2   
console.log(arr._indexOf(3, 100));//-1  

模拟实现了indexOf的基本使用!

模拟封装_lastIndexOf

Array.prototype._lastIndexOf = function (val, start) {
  var self = this;
  if (arguments.length == 0) {
    return -1;
  }

  if (arguments.length == 1) {
    return _searchFromEnd();
  }
  function _searchFromEnd() {
    for (var i = self.length - 1; i > 0; i--) {
      if (self[i] === val) {
        return i;
      }
    }
    return -1;
  }
  if (arguments.length >= 2) {
    //  传两个值,第二个格式不正确,默认从倒数最后一位即第0位开始查找,只是找一位.第1位是就返回0,不是返回-1
    if (typeof start !== "number" || isNaN(start)) {
      return self[0] === val ? 0 : -1;
    }
    // 否则就是数字,这里应该也有正负,所以也得转,正数是第几位。
    if (typeof start === "number" && !isNaN(start)) {
      // 到时第start位,正数是第几位呢
      start = -start + self.length;
      // 正后也有可能是负数或者正数,统一转为正。
      start = start >= 0 ? start : start + self.length;
      // console.log(start)
          // var temp = 0;
          for (var i = start; i > 0; i--) {
            // temp++;
            if (self[i] === val) {
              return i;//变成下标
            }
          }
          return -1;
    }
  }
}

测试

console.log(arr._lastIndexOf());//-1   什么都不传,返回-1
console.log(arr._lastIndexOf(3));//2    值传一个值,表示从倒数第1位开始查找
console.log(arr._lastIndexOf(3, 'a'));//-1   
 console.log(arr._lastIndexOf(1,'a'));//0   第二个格式不正确,默认从倒数最后一位开始查找,即只是对比数组第0位置。
console.log(arr._lastIndexOf(3, 2));//2   第二位是正常数值,从该位置开始向前查找

模拟实现了lastIndexOf的基本使用!

END

以上就是本文的所有内容

如有问题欢迎留言评论~