JS `Array.prototype.find()` / `findIndex()`:查找满足条件的第一个元素

各位听众,大家好!今天咱们来聊聊JavaScript中Array.prototype.find()Array.prototype.findIndex()这两个好兄弟,它们可是数组查找界的小能手,能帮你快速找到符合你心意的第一个元素。准备好了吗?咱们这就开始!

开场白:数组里寻宝记

想象一下,你是一个寻宝猎人,手里拿着一张藏宝图(数组),藏宝图上画着各种各样的宝藏(数组元素)。你的任务是找到符合特定描述的第一个宝藏。find()findIndex()就像你的寻宝工具,能帮你高效完成任务。

find():找到你想要的那个“它”

find()方法的作用是:找到数组中第一个满足提供的测试函数的元素的值。否则返回 undefined 简单来说,就是找到你想要的那个“它”,如果没找到,就告诉你“不存在”。

语法:

array.find(callback(element[, index[, array]])[, thisArg])
  • callback:为你定义的测试函数,对数组中的每个元素执行。
    • element:当前被处理的元素。
    • index (可选):当前被处理元素的索引。
    • array (可选):调用find()的数组本身。
  • thisArg (可选):执行callback时用作this的值。

举个栗子:

const numbers = [5, 12, 8, 130, 44];

const found = numbers.find(element => element > 10);

console.log(found); // 输出: 12

在这个例子中,我们想找到数组numbers中第一个大于10的数字。find()方法遍历数组,当遇到12时,element > 10返回true,于是find()就停下来,返回12。

再来一个栗子,这次是对象数组:

const inventory = [
  {name: 'apples', quantity: 2},
  {name: 'bananas', quantity: 0},
  {name: 'cherries', quantity: 5}
];

const result = inventory.find(fruit => fruit.name === 'cherries');

console.log(result); // 输出: {name: 'cherries', quantity: 5}

这次,我们想找到名字是’cherries’的水果。find()找到了,并返回了整个对象。

找不到怎么办?

const numbers = [1, 2, 3, 4, 5];

const found = numbers.find(element => element > 10);

console.log(found); // 输出: undefined

如果数组中没有满足条件的元素,find()会返回undefined

findIndex():找到“它”的位置

findIndex()方法的作用是:找到数组中第一个满足提供的测试函数的元素的索引。否则返回 -1 它和find()很像,只不过它不返回元素的值,而是返回元素的索引(位置)。如果找不到,就告诉你“-1”,代表“查无此人”。

语法:

array.findIndex(callback(element[, index[, array]])[, thisArg])

参数和find()完全一样。

举个栗子:

const numbers = [5, 12, 8, 130, 44];

const foundIndex = numbers.findIndex(element => element > 10);

console.log(foundIndex); // 输出: 1

这次,我们想找到数组numbers中第一个大于10的数字的索引。findIndex()找到了12,它的索引是1,所以返回1。

对象数组的栗子:

const inventory = [
  {name: 'apples', quantity: 2},
  {name: 'bananas', quantity: 0},
  {name: 'cherries', quantity: 5}
];

const resultIndex = inventory.findIndex(fruit => fruit.name === 'cherries');

console.log(resultIndex); // 输出: 2

我们想找到名字是’cherries’的水果的索引。findIndex()找到了,它的索引是2,所以返回2。

找不到怎么办?

const numbers = [1, 2, 3, 4, 5];

const foundIndex = numbers.findIndex(element => element > 10);

console.log(foundIndex); // 输出: -1

如果数组中没有满足条件的元素,findIndex()会返回-1。

find() vs findIndex():选择困难症?

现在你可能有点懵,find()findIndex()这么像,我该选哪个呢? 别慌,我来帮你分析一下:

特性 find() findIndex()
返回值 满足条件的第一个元素的值。找不到返回undefined 满足条件的第一个元素的索引。找不到返回-1
用途 需要元素的值时 需要元素的索引时
应用场景 查找某个具体对象,例如查找用户信息 删除数组中的特定元素(需要索引)

总结:

  • 如果你需要元素的值,就用find()
  • 如果你需要元素的索引,就用findIndex()

进阶用法:thisArg参数

thisArg参数允许你指定callback函数中this的值。 这在某些情况下很有用,尤其是在你使用类或对象的方法作为callback时。

举个栗子:

class Counter {
  constructor() {
    this.count = 0;
  }

  isGreaterThan(value) {
    this.count++;
    return value > this.threshold;
  }

  findFirstGreaterThan(array, threshold) {
    this.threshold = threshold;
    return array.find(this.isGreaterThan, this);
  }

  findIndexFirstGreaterThan(array, threshold) {
    this.threshold = threshold;
    return array.findIndex(this.isGreaterThan, this);
  }
}

const counter = new Counter();
const numbers = [1, 5, 10, 15, 20];

const found = counter.findFirstGreaterThan(numbers, 12);
const foundIndex = counter.findIndexFirstGreaterThan(numbers, 12);

console.log(found); // 输出: 15
console.log(foundIndex); // 输出: 3
console.log(counter.count); // 输出:2 (因为find和findIndex只遍历到满足条件的元素为止)

在这个例子中,我们定义了一个Counter类,它有一个isGreaterThan方法,用于判断一个值是否大于某个阈值。我们使用thisArg参数将this指向Counter实例,这样isGreaterThan方法才能访问this.threshold

注意事项:

  • find()findIndex()在找到第一个满足条件的元素后就会停止遍历,不会继续查找。
  • 如果数组是空的,find()findIndex()会立即返回undefined-1
  • find()findIndex()不会改变原始数组。

兼容性:

find()findIndex()是ES6中新增的方法,一些老版本的浏览器可能不支持。 你可以使用polyfill来解决兼容性问题。

一个简单的polyfill:

if (!Array.prototype.find) {
  Array.prototype.find = function(callback/*, thisArg*/) {
    'use strict';
    if (this == null) {
      throw new TypeError('Array.prototype.find called on null or undefined');
    }
    if (typeof callback !== 'function') {
      throw new TypeError('callback must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {
      value = list[i];
      if (callback.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}

if (!Array.prototype.findIndex) {
    Array.prototype.findIndex = function(predicate) {
      if (this == null) {
        throw new TypeError('"this" is null or not defined');
      }

      var o = Object(this);

      var len = o.length >>> 0;

      if (typeof predicate !== 'function') {
        throw new TypeError(predicate + ' is not a function');
      }

      var thisArg = arguments[1];

      for (var k = 0; k < len; k++) {
        if (k in o) {
          var kValue = o[k];
          if (predicate.call(thisArg, kValue, k, o)) {
            return k;
          }
        }
      }

      return -1;
    };
  }

实战演练:

假设你正在开发一个电商网站,你需要根据商品ID找到商品信息。

const products = [
  { id: 1, name: 'T-shirt', price: 20 },
  { id: 2, name: 'Jeans', price: 50 },
  { id: 3, name: 'Shoes', price: 80 }
];

function findProductById(productId) {
  return products.find(product => product.id === productId);
}

const product = findProductById(2);

console.log(product); // 输出: { id: 2, name: 'Jeans', price: 50 }

再来一个,假设你需要删除购物车中某个商品。

let cart = [
  { id: 1, name: 'T-shirt', quantity: 2 },
  { id: 2, name: 'Jeans', quantity: 1 },
  { id: 3, name: 'Shoes', quantity: 1 }
];

function removeProductFromCart(productId) {
  const index = cart.findIndex(item => item.id === productId);

  if (index !== -1) {
    cart.splice(index, 1);
  }
}

removeProductFromCart(2);

console.log(cart); // 输出: [ { id: 1, name: 'T-shirt', quantity: 2 }, { id: 3, name: 'Shoes', quantity: 1 } ]

总结:

find()findIndex()是JavaScript数组中非常有用的方法,它们能帮助你快速找到满足条件的第一个元素或元素的索引。 掌握它们,能让你的代码更加简洁高效。

课后练习:

  1. 创建一个包含学生对象的数组,每个学生对象包含namescore属性。
  2. 使用find()找到第一个成绩大于80分的学生。
  3. 使用findIndex()找到第一个成绩不及格的学生(成绩小于60分)的索引。

好了,今天的讲座就到这里。希望大家能掌握find()findIndex()的用法,在实际开发中灵活运用。 下次有机会再和大家分享其他有趣的JavaScript知识! 拜拜!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注