咱们好,我是哈默。indexOf 是咱们十分熟悉的一个办法,它可以用来获取某一个元素在一个数组里的方位,咱们一般就会运用 array.indexOf(element) 的办法来进行运用。

可是,咱们有没有运用过 indexOf 的第二个参数呢?第二个参数的运用会经常出现在一些优异的库的源码傍边,用于顺次剖析(或者说扫描)某一个字符串。

比如命令行美化输出的 chalk 库中就有此运用,由于 chalk 库的原理便是关于咱们输出在终端的内容进行处理,然后将处理后的字符串显示在终端上。

indexOf 根本用法

首要,咱们仍是先来回忆一下 indexOf 的最根本用法。

给定一个数组:[10, 20, 30],寻觅这个数组中 30 的方位,是 2

const arr = [10, 20, 30];
const element = 30;
const index = arr.indexOf(element);
console.log(index); // 2

indexOf 的第二个参数

明确了 indexOf 的根本用法今后,它的第 2 个参数有什么用呢?

其实是起到了一个调整从哪里开端查找的效果。

咱们来看一个比如:

const arr = [10, 20, 30];
const element = 10;
const index = arr.indexOf(element);
console.log(index); // 0
const arr2 = [10, 20, 30, 10];
const element2 = 10;
const index2 = arr2.indexOf(element2, 1);
console.log(index2); // 3

可以看到,同样是查找 [10, 20, 30, 10] 傍边 10 的方位,可是由于第一次是从数组第 1 个元素开端查找的,所以得到的成果是 0。

而第二次是从数组的第 2 个元素开端查找的,所以得到的成果是 3。

优异库源码里的运用

明确了 indexOf 第二个参数的运用之后,咱们再来看一下在一些优异的库的源码里面,它们是如何利用起这个第二个参数的效果的。

这儿,咱们只会剖析它的思维,具体的实现在具体的源码里会存在差异,但思维是相同的。

咱们首要定义一个办法,addEmoji,承受三个参数:

/**
 * 在一个 string 的 targetString 后边,加上一个 emoji
 * @param string 原始 string
 * @param targetString 加 emoji 的那个 string
 * @param emoji 加入的 emoji
 * @returns 处理后的终究成果
 */
function addEmoji(string, targetString, emoji) {
  let result = "";
  // 一系列处理
  // ...
  return result;
}

咱们终究会这样调用,在 咱们好,我是哈默,今天是一个好天气。 这个字的后边,加上 的 emoji:

const res = addEmoji("咱们好,我是哈默,今天是一个好天气。", "好", "");
console.log(res);

那么首要咱们就可以运用 indexOf 办法来从输入的字符串里找到 的方位:

function addEmoji(string, targetString, emoji) {
  // 找到 targetString 的方位
  let index = string.indexOf(targetString);
  let result = "";
  // 记载当时扫描到的方位,现在是在参数 string 的最初方位
  // 由于 string 傍边,可能会存在多个 targetString,所以咱们会跳着进行扫描,也便是会运用 indexOf 的第二个参数
  let currentScanIndex = 0;
  return result;
}

假如咱们找到了 targetString,即 index !== -1,那么咱们就在 targetString 后,加上一个 emoji:

function addEmoji(string, targetString, emoji) {
  // 找到 targetString 的方位
  let index = string.indexOf(targetString);
  let result = "";
  // 记载当时扫描到的方位,现在是在参数 string 的最初方位
  // 由于 string 傍边,可能会存在多个 targetString,所以咱们会跳着进行扫描,也便是会运用 indexOf 的第二个参数
  let currentScanIndex = 0;
  // 假如找到了 targetString
  if (index !== -1) {
    // 在 targetString 后边添加 emoji
    result += string.slice(currentScanIndex, index) + targetString + emoji;
    // 将当时扫描方位,移动到 targetString 之后的那个方位上
    currentScanIndex = index + targetString.length;
  }
  // 将 targetString 之后的内容追加到 result 里
  result += string.slice(currentScanIndex);
  return result;
}

此刻,咱们在第一个 字后边,加上了 ,得到的成果:

indexOf的第二个参数你用过嘛

可是,咱们这个字符串中,还有一个 好天气,也便是存在多个 targetString,所以咱们这儿不能是 if 只执行一次,而是要做一个循环。

咱们可以运用一个 while 循环:

function addEmoji(string, targetString, emoji) {
  // 找到 targetString 的方位
  let index = string.indexOf(targetString);
  let result = "";
  // 记载当时扫描到的方位,现在是在参数 string 的最初方位
  // 由于 string 傍边,可能会存在多个 targetString,所以咱们会跳着进行扫描,也便是会运用 indexOf 的第二个参数
  let currentScanIndex = 0;
  // 假如找到了 targetString
  while (index !== -1) {
    // 在 targetString 后边添加 emoji
    result += string.slice(currentScanIndex, index) + targetString + emoji;
    // 将当时扫描方位,移动到 targetString 之后的那个方位上
    currentScanIndex = index + targetString.length;
+   // 要点来了!!!咱们要从当时扫描的方位开端,去寻觅 targetString
+   index = string.indexOf(targetString, currentScanIndex);
  }
  // 将 targetString 之后的内容追加到 result 里
  result += string.slice(currentScanIndex);
  return result;
}

此刻,咱们便成功的给第二个 ,也加上了 emoji:

indexOf的第二个参数你用过嘛

这个地方咱们就运用到了之前提到的 indexOf 的第二个参数:

// 要点来了!!!咱们要从当时扫描的方位开端,去寻觅 targetString
index = string.indexOf(targetString, currentScanIndex);

咱们是从当时扫描到的方位 currentScanIndex 开端,查找 targetString 的,这样咱们就可以找到下一个 targetString 了。

所以,这儿的思维便是通过 indexOf 的第二个参数,帮助咱们可以顺次扫描一个字符串,顺次找到咱们想要找的那个元素的方位,然后做相应的处理。

总结

indexOf 的第二个参数,叫 fromIndex,看到这儿,咱们应该也能很好的理解这个 fromIndex 的效果了,便是从哪里开端找嘛!