Skip to content

目录:

一、介绍

二、个人手写

1、个人未看源码思路

2、个人手写代码

三、源码分析

1、源码思路

四、总结

字数:大约900字

一、介绍

名称:array-first

地址:https://github.com/jonschlinkert/array-first.git

示例:

js
var first = require('array-first');

first(['a', 'b', 'c', 'd', 'e', 'f']);
//=> 'a'

first(['a', 'b', 'c', 'd', 'e', 'f'], 1);
//=> 'a'

first(['a', 'b', 'c', 'd', 'e', 'f'], 3);
//=> ['a', 'b', 'c']

可能很多人一看就知道怎么实现,但是看源码、手写源码,都应该循序渐进,先从简单的开始,写多了之后,遇到复杂的也有思路、有逻辑、有规范的去实现。

二、个人手写

都是没有看源码前的手写。对比之后才能学到更多,更深刻。同样的,如果是我们自己手写,你应该怎样写,看起来好像很简单。

1、个人未看源码思路

1、判断是否是数组、判断是否有第二个参数

2、如果没有第二个参数,默认返回数组第一个数据。第二个参数为1也一样。

3、如果有第二个参数,判断大小,如果大于1,则返回截取原数据长度为第二个参数的新数组。因为是返回数组的前面数据,所以就不考虑第二个参数为负数的时候啦。

按照这个思路,我们实现的代码是这样的:

2、个人手写代码

js
const first = (list: string[], size?: number)  => {
  // 不是数组则提示
  if(!Array.isArray(list)) throw new Error("list is not a Array!");
  // 如果为空数组,提示需要至少有一个
  if(!list?.length)  throw new Error("list length must larger than 0!");
  // 没有第二个参数或者第二个参数为1。返回数组第一个
  if(!size || size === 1) return list[0];
  // 如果第二个参数小于数组长度则截取
  if(size < list.length) return list.splice(0, size)
  // 如果第二个参数大于等于数组长度则直接返回数组
  return list;
}

测试

js
first(['a', 'b', 'c', 'd', 'e', 'f']);
//=> 'a'

first(['a', 'b', 'c', 'd', 'e', 'f'], 1);
//=> 'a'

first(['a', 'b', 'c', 'd', 'e', 'f'], 3);
//=> ['a', 'b', 'c']

first(['a', 'b', 'c', 'd', 'e', 'f'], 8);
//=> ['a', 'b', 'c', 'd', 'e', 'f']

这样,我们的代码就写出来了。

三、源码分析

那我们就要看看人家写的源码。

js
function arrayFirst(arr, num) {
  if (!Array.isArray(arr)) {
    throw new Error('array-first expects an array as the first argument.');
  }

  if (arr.length === 0) {
    return null;
  }

  var first = slice(arr, 0, isNumber(num) ? +num : 1);
  if (+num === 1 || num == null) {
    return first[0];
  }
  return first;
};

function isNumber(num) {
  if (typeof num === 'number') {
    return num - num === 0;
  }
  if (typeof num === 'string' && num.trim() !== '') {
    return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
  }
  return false;
};

1、源码思路

同样:

首先判断是否是数组

再判断数组长度

然后他用了js数组的slice方法。并且调用了isNumber方法。之前文章说过,finite检查一个数值是否为有限的,即不是Infinity。如果参数类型不是数值,Number.isFinite一律返回false。所以知道,它如果传的第二个参数不是数字,统一视为1。否则slice第二个参数为正的number。他是不管怎样都去截取数组,个人认为不合理。如果大于了数组长度再去截取,不就是浪费性能啦。

当然它对第二个参数的判断更充分,我这里只是用了ts限制了。如果不用ts,就会有问题。

还有就是以后都尽可能用ts来写啦。让大家习惯看ts。也会慢慢成长的。不熟悉的可以看看往期ts的教程。

四、总结

1、写功能模块时,可以引用好的第三方依赖,当然主要逻辑尽可能用自己的,不然就失去了自己写的意义了,那就叫般啦