事件起因

查看技术文档的时候看到了数组的深度遍历,但是博主只写了一种方法,所以想着去查找更简洁的代码来实现.
于是去看了JavaScript Array的文档然后发现文档中有很多"不起眼"的API,随之注意到了Array.at(),于是乎讨论起来了Array.at()的实现方式(想着应该不会用我们的思想封装一个Len+负数实现从后面取数据的方式吧)

开始折腾

于是讨论着就去看了源码的实现方式.

// 局部代码如下
at: function at(index) {
  var O = toObject(this); // 如果this不是undefined将它转成object类型
  var len = lengthOfArrayLike(O); // 获取数组长度
  // 获取传入的下标值 可以为字符串<但必须可以转数值的字符串才行>
  var relativeIndex = toIntegerOrInfinity(index); 
  // 如果 传入下标值大于等于0则使用这个下标值否则使用数组长度减去这个下标值
  var k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;
  // 如果k越界则返回undefined否则返回该数组k下标下的值
  return (k < 0 || k >= len) ? undefined : O[k];
}

// 获取数组长度
function lengthOfArrayLike (obj) {
  // 将数组长度进行过滤
  return toLength(obj.length);
};

// 过滤数组长度为正整数且不会越界 异常则返回0
function toLength(argument) {
  // 2 ** 53 - 1 == 9007199254740991
  return argument > 0 ? min(toIntegerOrInfinity(argument), 0x1FFFFFFFFFFFFF) : 0;
};

// 这个地方验证比较绕,主要目的是为了得到一个整数值
function toIntegerOrInfinity(argument) {
  var ceil = Math.ceil;
  var floor = Math.floor;
  var number = +argument; // 防止argument为字符串将其转为数值型
  // number !== number    NaN!==NaN   或者 number为0   返回0  
  //否则大于0或小于0的小数则向0靠齐
  return number !== number || number === 0 ? 0 : (number > 0 ? floor : ceil)(number);
};

image-1652468262073

得出结论

Array.at(-1) 等价于 Array[Array.length-1] 但经过简单的测试后者相对较快

  <script>
    // 创建一个数组填充1-99999
    let arr = [];
    for (let i = 0; i < 740991; i++) {
      arr.push(i);
    }
    // 开始计时
    let start = new Date().getTime();
    console.log("start: ", start);
    // 随机获取1000次数组元素使用at
    for (let i = 0; i < 1000; i++) {
      let index = Math.floor(Math.random() * arr.length);
      let item = arr.at(index);
    }
    // 计时结束
    let end = new Date().getTime();
    console.log("end: ", end);
    // 开始计时
    start = new Date().getTime();
    console.log("start: ", start);
    // 随机获取1000次数组元素使用[index]
    for (let i = 0; i < 1000; i++) {
      let index = Math.floor(Math.random() * arr.length);
      let item = arr[index];
    }
    // 计时结束
    end = new Date().getTime();
    console.log("end: ", end);
  </script>

image-1652468987293
经过反复思考最后想到了Array.at()的几点好处

  1. 使代码变得简短整洁
  2. 防止有大聪明把length拼错了
  3. … … 欢迎补充

总结

被 number !== number 卡住后来提了个issues(丢人了一把)作者给了提示才反应过来 NaN !== NaN
image-1652506259525

Q.E.D.


远赴人间惊鸿宴,一睹人间盛世颜。