本篇按顺序看下接下来的几个零散的小方法,包括head
、tail
、indexOf
、initial
、nth
、nthArg
,最后给出几个方法的原生实现。
引用的内置方法
主要是indexOf
和lastIndexOf
两个方法用到了内置方法strictIndexOf
和strictLastIndexOf
。其实使用strict
的原因是为了避免NaN
的影响,因为在 JS 中NaN === NaN
为假,所以当值不为NaN
时才使用严格相等判断;如果值为NaN
,就会使用特殊的baseFindIndex
和baseIsNaN
组合起来判断。
strictLastIndexOf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
function strictLastIndexOf(array, value, fromIndex) { let index = fromIndex + 1; while (index--) { if (array[index] === value) { return index; } } return index; }
export default strictLastIndexOf;
|
lodash 方法
head
head
方法其实用的就是数组下标实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
function head(array) { return array != null && array.length ? array[0] : undefined; }
export default head;
|
tail
tail
方法使用的是扩展运算符进行数组解构实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
function tail(array) { const length = array == null ? 0 : array.length; if (!length) { return []; } const [, ...result] = array; return result; }
export default tail;
|
indexOf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import baseIndexOf from './.internal/baseIndexOf.js'; import toInteger from './toInteger.js';
function indexOf(array, value, fromIndex) { const length = array == null ? 0 : array.length; if (!length) { return -1; } let index = fromIndex == null ? 0 : toInteger(fromIndex); if (index < 0) { index = Math.max(length + index, 0); } return baseIndexOf(array, value, index); }
export default indexOf;
|
lastIndexOf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import baseFindIndex from './.internal/baseFindIndex.js'; import baseIsNaN from './.internal/baseIsNaN.js'; import strictLastIndexOf from './.internal/strictLastIndexOf.js'; import toInteger from './toInteger.js';
function lastIndexOf(array, value, fromIndex) { const length = array == null ? 0 : array.length; if (!length) { return -1; } let index = length; if (fromIndex !== undefined) { index = toInteger(fromIndex); index = index < 0 ? Math.max(length + index, 0) : Math.min(index, length - 1); } return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true); }
export default lastIndexOf;
|
initial
这里不使用扩展运算符,是因为扩展运算符只能是最后一个元素,所以就老老实实使用 slice。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import slice from './slice.js';
function initial(array) { const length = array == null ? 0 : array.length; return length ? slice(array, 0, -1) : []; }
export default initial;
|
last
last
和head
方法差不多,也是用的数组下标实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
function last(array) { const length = array == null ? 0 : array.length; return length ? array[length - 1] : undefined; }
export default last;
|
nth
nth
方法和last
及head
的实现类似,只不过多了索引的验证和负数索引的处理。这里的负数索引n += n < 0 ? length : 0;
转换的很干脆,学习一波。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import isIndex from './.internal/isIndex.js';
function nth(array, n) { const length = array == null ? 0 : array.length; if (!length) { return; } n += n < 0 ? length : 0; return isIndex(n, length) ? array[n] : undefined; }
export default nth;
|
nthArg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import nth from './nth.js';
function nthArg(n) { return (...args) => nth(args, n); }
export default nthArg;
|
原生实现
其实head
、tail
、initial
、last
的原生实现方式和 lodash 实现过程差不多,只不过自己写的时候没有必要加那么多的参数判断。
head 和 tail
1 2 3 4 5 6 7
| const array = [1, 2, 3]; const [head, ...tail] = array; console.log(head);
console.log(tail);
|
initial
1 2 3 4
| const array = [5, 4, 3, 2, 1] console.log(array.slice(0, -1););
|
indexOf 和 lastIndexOf
这两个方法本身ES5
就是原生实现了的。
1 2 3 4 5 6
| var array = [2, 9, 9, 4, 3, 6]; console.log(array.indexOf(9));
console.log(array.lastIndexOf(9));
|