Lodash源码阅读-last

功能概述

last 函数是 Lodash 中的一个实用数组方法,主要用于获取数组的最后一个元素。与 head 函数获取第一个元素相对应,last 函数获取数组的末尾元素。这个函数同样处理了各种边缘情况,如空数组、null 或 undefined 输入等。

源码实现

js 复制代码
function last(array) {
  var length = array == null ? 0 : array.length;
  return length ? array[length - 1] : undefined;
}

实现原理解析

原理概述

last 函数的实现原理清晰明了:首先获取数组的长度,如果数组有效且长度大于 0,则返回数组的最后一个元素(索引为 length - 1 的元素);否则返回 undefined。这种实现方式安全地处理了各种边缘情况,包括 null、undefined 和空数组输入,同时保持了代码的简洁性和可读性。

整个过程可以概括为:

  1. 获取输入数组的长度,处理 null 和 undefined 的情况
  2. 检查长度是否为真值(大于 0)
  3. 如果长度大于 0,返回最后一个元素;否则返回 undefined

代码解析

1. 获取数组长度

js 复制代码
var length = array == null ? 0 : array.length;

这行代码首先处理了数组可能为 null 或 undefined 的情况:

  • array == null 是一个简洁的检查,它同时匹配 array === nullarray === undefined
  • 如果 array 是 null 或 undefined,则将 length 设置为 0
  • 否则,获取 array.length 作为数组长度

示例:

js 复制代码
// 当传入正常数组时
var arr = [1, 2, 3];
var length = arr == null ? 0 : arr.length; // length = 3

// 当传入空数组时
var arr = [];
var length = arr == null ? 0 : arr.length; // length = 0

// 当传入 null 时
var arr = null;
var length = arr == null ? 0 : arr.length; // length = 0

// 当传入 undefined 时
var arr = undefined;
var length = arr == null ? 0 : arr.length; // length = 0

// 当传入非数组对象时
var arr = { a: 1 };
var length = arr == null ? 0 : arr.length; // length = undefined

2. 条件返回最后一个元素

js 复制代码
return length ? array[length - 1] : undefined;

这行代码使用三元操作符根据 length 的值决定返回什么:

  • 如果 length 为真值(大于 0),返回 array[length - 1](最后一个元素)
  • 否则返回 undefined

示例:

js 复制代码
// 有效非空数组
last([1, 2, 3]); // length = 3,返回 array[2],即 3

// 只有一个元素的数组
last([42]); // length = 1,返回 array[0],即 42

// 空数组
last([]); // length = 0,返回 undefined

// null 或 undefined
last(null); // length = 0,返回 undefined
last(undefined); // length = 0,返回 undefined

// 非数组对象
last({}); // length = undefined,在布尔上下文中为 false,返回 undefined

使用示例

js 复制代码
// 获取普通数组的最后一个元素
_.last([1, 2, 3]);
// => 3

// 处理只有一个元素的数组
_.last([42]);
// => 42

// 处理空数组
_.last([]);
// => undefined

// 处理 null 或 undefined
_.last(null);
// => undefined
_.last(undefined);
// => undefined

// 处理字符串(类数组对象)
_.last("abc");
// => 'c'

// 处理类数组对象
_.last({ 0: "a", 1: "b", length: 2 });
// => 'b'

与其他方法的比较

  1. last vs Array.prototype.slice:与使用 slice(-1)[0] 相比,last 函数更简洁且处理了边缘情况。
js 复制代码
// 使用 slice 获取最后一个元素
[1, 2, 3].slice(-1)[0]; // 3

// 但 slice 在处理 null 或 undefined 时会出错
// null.slice(-1)[0]; // TypeError: Cannot read property 'slice' of null

// last 函数安全处理边缘情况
_.last(null); // undefined
  1. last vs Array.prototype.pop:与 pop 不同,last 不会修改原数组。
js 复制代码
const arr = [1, 2, 3];

// pop 会移除并返回最后一个元素
arr.pop(); // 返回 3
console.log(arr); // [1, 2]

// last 不会修改原数组
const newArr = [1, 2, 3];
_.last(newArr); // 返回 3
console.log(newArr); // 仍然是 [1, 2, 3]
  1. last vs 直接索引访问:与直接使用 array[array.length - 1] 相比,last 函数处理了边缘情况。
js 复制代码
// 直接索引访问可能导致错误
// null[null.length - 1]; // TypeError

// 空数组直接访问会返回 undefined,但代码不够优雅
[][].length - 1]; // undefined,但写法复杂且容易出错

// last 函数提供了更安全、更简洁的方式
_.last(null); // undefined
_.last([]); // undefined

注意事项

  1. 返回 undefined 的情况:last 函数在以下情况会返回 undefined:

    • 输入是空数组 []
    • 输入是 null 或 undefined
    • 输入是没有 length 属性的对象
    • 输入是 length 为 0 的类数组对象
  2. 类数组对象:last 函数可以处理类数组对象,但需要注意索引和 length 属性的一致性。

js 复制代码
// 字符串是类数组对象
_.last("hello"); // 'o'

// 自定义类数组对象
const arrayLike = { 0: "a", 1: "b", length: 2 };
_.last(arrayLike); // 'b'

// 但如果 length 属性与实际索引不匹配,可能得到意外结果
const mismatchedArrayLike = { 0: "a", 1: "b", length: 3 };
_.last(mismatchedArrayLike); // undefined,因为索引 2 处没有值

总结

Lodash 的 last 函数是一个简单但实用的工具,它通过简洁的代码安全地获取数组的最后一个元素。虽然功能看似基础,但它处理了各种边缘情况,使代码更加健壮和可靠。

相关推荐
陈天伟教授3 小时前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
信看4 小时前
NMEA-GNSS-RTK 定位html小工具
前端·javascript·html
Tony Bai4 小时前
【API 设计之道】04 字段掩码模式:让前端决定后端返回什么
前端
爱吃大芒果4 小时前
Flutter 主题与深色模式:全局样式统一与动态切换
开发语言·javascript·flutter·ecmascript·gitcode
苏打水com4 小时前
第十四篇:Day40-42 前端架构设计入门——从“功能实现”到“架构思维”(对标职场“大型项目架构”需求)
前端·架构
king王一帅4 小时前
流式渲染 Incremark、ant-design-x markdown、streammarkdown-vue 全流程方案对比
前端·javascript·人工智能
苏打水com4 小时前
第十八篇:Day52-54 前端跨端开发进阶——从“多端适配”到“跨端统一”(对标职场“全栈化”需求)
前端
Bigger5 小时前
后端拒写接口?前端硬核自救:纯前端实现静态资源下载全链路解析
前端·浏览器·vite
BD_Marathon5 小时前
【JavaWeb】路径问题_前端绝对路径问题
前端