📕 重学JavaScript:如何手写一个`pop`高阶函数?

简介: `pop` 高阶函数是一个非常常用的数组方法,可以让你用一种简单的方法来删除数组里的元素。

📕 重学JavaScript:如何手写一个pop高阶函数?

嗨,大家好!这里是道长王jj~ 🎩🧙‍♂️

pop 高阶函数是一个非常常用的数组方法,可以让你用一种简单的方法来删除数组里的元素。

pop可以让你把数组的最后一个元素拿出来,并返回它。

比如,你可以用pop来拿出数组里的4,并返回它,让数组变成[1, 2, 3]。😊

在ECMA中,也就是一群很聪明的人制定的一些规则中,他们已经给我们解释了pop方法是怎么工作的。

他们用了一段伪代码,也就是一种类似于真正代码但是不完全一样的东西,来描述pop方法的每一个步骤:

1. Let O be ? ToObject(this value).
2. Let len be ? LengthOfArrayLike(O).
3. If len = 0, then
    a. Perform ? Set(O, "length", +0𝔽, true).
    b. Return undefined.
4. Else,
    a. Assert: len > 0.
    b. Let newLen be 𝔽(len - 1).
    c. Let index be ! ToString(newLen).
    d. Let element be ? Get(O, index).
    e. Perform ? DeletePropertyOrThrow(O, index).
    f. Perform ? Set(O, "length", newLen, true).
    g. Return element.

好的,根据这个原理,我们可以用JavaScript来实现我们的目标。😎

⭕ 解答一部分实现的关键逻辑

把调用push函数的值转换成一个对象(ToObject)。

保证 push 函数可以接受任何类型的值作为参数,比如字符串、数字、布尔等,不会因为用户传入的差异导致报错。

// 假设我们有一个数组arr
let arr = [1, 2, 3, 4];
// 把它转换成一个对象O
let O = Object(arr);

获取对象的长度(LengthOfArrayLike)

确定我们需要遍历对象中的多少个元素

// 获取对象O的所有属性名
let keys = Object.keys(O);
// 获取它们的个数,也就是对象O的长度len
let len = keys.length;

删除对象里对应的值

使用delete的时候,原数组的length不会变更,需要同步更改。

delete O[index];
O.length--;

其他的都是口水话,很简单,这里我就不过多解释了,接下来直接上源码。

💌 完整代码解析如下:

function pop() {
   
  // 把数组变成一个对象
  let O = Object(this);
  // 把对象的长度记下来
  let len = Object.keys(O).length;
  // 检查一下对象是否为空,也就是长度是否为0
  if (len === 0) {
   
    // 如果是,就做以下事情
    // 把对象的长度更新为0,并叫做"length"
    O.length = 0;
    // 返回undefined
    return undefined;
  }
  // 如果对象不为空,就做以下事情
  else {
   
    // 把对象的长度减1,并叫做newLen
    let newLen = len - 1;
    // 把newLen转换成字符串,并叫做index
    let index = String(newLen);
    // 把对象里index这个属性对应的值赋给一个变量叫做element
    let element = O[index];
    // 删除对象里index这个属性及其对应的值
    delete O[index];
    // 把对象的长度更新为newLen,并叫做"length"
    O.length = newLen;
    // 返回element
    return element;
  }
}

这个方法其实没什么难点。

💨 我们试一下是否能实现效果

let arr = [1, 2, 3, 4];
let result = arr.pop();
// 4
console.log(result);
// [1, 2, 3]
console.log(arr);

✔ V8引擎中的map源码是怎么实现的呢?

我在这里直接粘贴给大家看看,大家自行对比一下:

// Removes the last element from the array and returns it. See
// ECMA-262, section 15.4.4.6.
function ArrayPop() {
   
  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");

  var array = TO_OBJECT(this);
  var n = TO_LENGTH(array.length);
  if (n == 0) {
   
    array.length = n;
    return;
  }

  n--;
  var value = array[n];
  %DeleteProperty_Strict(array, n);
  array.length = n;
  return value;
}

📕 参考资料

V8数组部分源码第393行

ecma262草案


🎉 你觉得怎么样?这篇文章可以给你带来帮助吗?如果你有任何疑问或者想进一步讨论相关话题,请随时发表评论分享您的想法,让其他人从中受益。🚀✨

目录
相关文章
|
前端开发 JavaScript
前端基础 - JavaScript高级应用(高阶函数)
前端基础 - JavaScript高级应用(高阶函数)
58 0
|
存储 JavaScript 前端开发
js数组高阶函数——includes()方法
js数组高阶函数——includes()方法
322 0
|
2月前
|
JSON JavaScript 前端开发
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
|
1月前
|
前端开发 JavaScript 索引
JavaScript 数组常用高阶函数总结,包括插入,删除,更新,反转,排序等,如map、splice等
JavaScript数组的常用高阶函数,包括遍历、插入、删除、更新、反转和排序等操作,如map、splice、push、pop、reverse等。
18 0
|
5月前
|
JavaScript 前端开发 测试技术
JavaScript进阶-高阶函数与柯里化
【6月更文挑战第18天】在JavaScript中,高阶函数和柯里化是函数式编程的核心。高阶函数接收或返回函数,常用于数组操作和事件处理。柯里化将多参数函数转化为单参数的逐次求值过程,用于参数预绑定和函数组合。两者能简化逻辑、提高复用性,但也需注意易错点,如混淆参数、过度柯里化,应适度使用并配合测试保证正确性。通过实践和使用工具,如lodash的`_.curry`,能更好地利用这些技术。
47 5
|
6月前
|
JavaScript 前端开发 测试技术
JavaScript中的函数式编程:纯函数与高阶函数的概念解析
【4月更文挑战第22天】了解JavaScript中的函数式编程,关键在于纯函数和高阶函数。纯函数有确定输出和无副作用,利于预测、测试和维护。例如,`add(a, b)`函数即为纯函数。高阶函数接受或返回函数,用于抽象、复用和组合,如`map`、`filter`。函数式编程能提升代码可读性、可维护性和测试性,帮助构建高效应用。
|
6月前
|
前端开发 JavaScript 容器
早期 JavaScript 中的高阶函数与模块化实现
早期 JavaScript 中的高阶函数与模块化实现
|
6月前
|
JavaScript 前端开发
JavaScript中高阶函数与闭包的实际应用
【4月更文挑战第22天】JavaScript中的高阶函数和闭包是强大的工具,常用于抽象、复用和构建组合逻辑。高阶函数如回调、数组方法和函数组合能提高代码灵活性。闭包则用于封装私有变量、创建函数工厂和在异步编程中保留上下文。两者结合使用,如`createAccumulator`函数,能创建更灵活的代码结构。
|
6月前
|
JavaScript 安全 前端开发
高阶函数(js的问题)
高阶函数(js的问题)
31 0
|
6月前
|
存储 前端开发 JavaScript
JavaScript 中的高阶函数
JavaScript 中的高阶函数