function initial(array)
获取数组中除了最后一个元素之外的所有元素
(ps:前面看了这么多代码,不用看都猜到是参数合法后,调用baseSlice了)
@param {Array} array The array to query.
要查询的数组
function initial(array) {
// 拿取数组长度
var length = array == null ? 0 : array.length;
// 数组长度存在则调用截取方法,否则返回空数组
return length ? baseSlice(array, 0, -1) : [];
}
function join(array, separator)
将数组中的所有元素转换为由 separator 分隔的字符串。
@param {Array} array The array to convert.
需要转换的数组
@param {string} [separator=','] The element separator.
分隔符
function join(array, separator) {
// 数组参数没有传递的话,返回空字符串
// 否则调用nativeJoin,并用call改变函数指向
return array == null ? '' : nativeJoin.call(array, separator);
}
(但实际上,lodash的开发还是偷了些懒,这个nativeJoin
源自arrayProto
中的join
,而arrayProto
则被赋值为Array.prototype
,所以join
方法直接用的JavaScript
原生的。不过用纯JS实现的话,其实也比较简单,遍历数组,并根据分隔符是否传递而决定输出内容[拼接字符串])
function last(array)
获取数组中的最后一个元素
@param {Array} array The array to query.
要检索的数组
function last(array) {
// 获取数组长度
var length = array == null ? 0 : array.length;
// 长度存在 = 数组有内容 》》》 返回最后一个参数
// 不存在说明数组本身为空或者其他,返回undefined
return length ? array[length - 1] : undefined;
}
function lastIndexOf(array, value, fromIndex)
这个方法类似 _.indexOf,除了它是从右到左遍历元素的
@param {Array} array The array to inspect.
需要检索的数组
@param {*} value The value to search for.
要检索的值
@param {number} [fromIndex=array.length-1] The index to search from.
检索 index 的起点
function lastIndexOf(array, value, fromIndex) {
// 老规矩,先来判定数组的长度,也就是数组是否是对于该函数合法的数组
var length = array == null ? 0 : array.length;
if (!length) {
// 若数组为空或其他,返回-1
return -1;
}
// lastIndexOf 是从右到左遍历,所以index[第三个参数]默认情况下为数组的长度
var index = length;
// 现在来判断第三个参数是否传递,若为传递,该参数为undefined
if (fromIndex !== undefined) {
// 此条件下,该参数有内容,使用toInteger将参数转化为有效的数字
index = toInteger(fromIndex);
// 如果转化后该参数小于零,那么为其增加数组长度的数值,最小不低于0
// 如果转化后该参数大于零,那么和数组最大索引比较,最大不超过数组索引
index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
}
// value === value 这一步确实不明白用意为何?
// 默认是直接调用strictLastIndexOf,和indexOf调用的strictIndexOf有区别
// 注意index是先设置默认值,在判断是否传参,因为先处理的话,toInteger也能够将undefined转化为对应的数字
return value === value
? strictLastIndexOf(array, value, index)
: baseFindIndex(array, baseIsNaN, index, true);
}
接lastIndexOf
function strictLastIndexOf(array, value, fromIndex) {
// 注意在lastIndexOf中,传递过来的fromIndex参数是该数组的最大索引,而不是数组的长度
// 这里把fromIndex+1和获取array.length作用是相同的,不必纠结
var index = fromIndex + 1;
// 遍历,从右到左,所以是index--
while (index--) {
// 判断要查询的值,需要用全等于,如果是 ==,那么会发生隐式数据类型转换,
if (array[index] === value) {
// 返回索引值
return index;
}
}
// 如果一直遍历到没有结果,那么当时条件不成立时,index的值是0
// 而在此处,return时又调用了一次index,那么会执行 index-1 的操作,所以可以返回 -1
return index;
}
function reverse(array)
反转数组,第一个元素移动到最后一位,第二个元素移动到倒数第二,类似这样。
@param {Array} array The array to modify.
function reverse(array) {
// 数组存在且调用reverse,不存在返回该值本身
return array == null ? array : nativeReverse.call(array);
}
(该方法也是直接使用的JavaScript
原型方法,要写原生JS的话也能够实现最基本的,因为reverse
是会改变原数组的顺序,所以大致代码如下:)
var reverseNew = function (array) {
// 拷贝数组内容
const arrayCopy = [...array]
// 取出长度
let length = array.length
// 重新赋值的洗标
let index = 0
// 循环copy数组
while (length) {
// 对原数组内容重新赋值,index++和--length可以保证在下一次循环时能够获取到对应下标的内容,并且循环正常进行
array[index++] = arrayCopy[--length]
}
}
本来打算看pull
的,但是pull
在lodash里的调用好像有点复杂,不过pull
最终是指向pullAll
这个方法,所以先了解pullAll
—————
function pullAll(array, values)
这个方式类似 _.pull,除了它接受数组形式的一系列值。
@param {Array} array The array to modify.
需要调整的数组
@param {Array} values The values to remove.
要移除的值[数组形式]
(ps:看代码前的个人猜想,因为第二个参数是数组形式,basePullAll
会不会调用lodash内部的baseIndexOf
?)
function pullAll(array, values) {
// 新的判断方式,数组存在 且 长度不为0或undefined 且 第二个参数存在 且 第二个参数长度不为0或undefined
return (array && array.length && values && values.length)
// 以上条件都满足,调用basePullAll并传入参数
? basePullAll(array, values)
// 否则返回原数组
: array;
}
function basePullAll(array, values, iteratee, comparator)
pullAllBy的基本实现,不支持iteratee缩写。(只能机翻哈,英语水平不是太好)
@param {Array} array The array to modify.
要修改的数组
@param {Array} values The values to remove.
要删除的值[type 数组]
@param {Function} [iteratee] The iteratee invoked per element.
每个元素调用的iteratee[iteratee应该是迭代函数]
@param {Function} [comparator] The comparator invoked per element.
每个元素调用的比较器
(后面basePullAll
调用到的相关方法也写在下面了)
function basePullAll(array, values, iteratee, comparator) {
// 第四个参数是否存在,存在则使用baseIndexOfWith方法,不存在则使用baseIndexOf
var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
// 数组循环的初始下标
index = -1,
// 删除数组的长度
length = values.length,
// 拷贝一份数组(地址?)
seen = array;
if (array === values) {
// 如果原数组和删除数数组都存在,那么重新拷贝一份删除数组?
values = copyArray(values);
}
if (iteratee) {
// 如果第三个参数存在(函数参数),则表示要对原数组中的每一项内容做修改
// 调用 _.map 的基础版本,将其修改内容后的数组重新赋值给 seen
seen = arrayMap(array, baseUnary(iteratee));
}
// 循环(比对删除数组的长度)
while (++index < length) {
// indexOf查询到该值的下标,默认为0
var fromIndex = 0,
// 拿到当前需要被删除的变量
value = values[index],
// 需要被查找的变量,如果iteratee存在,那么将处理该值(之前处理的是原数组,这次处理的是删除数组)
computed = iteratee ? iteratee(value) : value;
// 如果调用indexOf能够在seen里找到对应元素的下标
// indexOf调用,传递参数,seen[处理后的数组]、computed[需要查询的项]、fromIndex[查询时的起始下标]、comparator[比较器]
// 如果数组中有多个该项存在,那么循环会一直成立,直到找不到该值为止
while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
// 如果处理后的数组和原数组不同(如,原数组中混杂有字符串和数字,而处理后的数组是将其都转化成数字,那么这样是不同的)
if (seen !== array) {
// 那么处理后的数组也要删除对应的该项
// 此项成立的条件在于,iteratee参数是否传递,而indexOf查询的基础是在seen上
// 如果iteratee没有传递,那么在方法开头,seen=array,此时删除array本身的内容,seen也会跟随变动
// 而iteratee传递之后,两个数组必然不相等,那么seen也要同步array被删除的项,否则该循环会一直存在,直到array数组内容全部被清空
splice.call(seen, fromIndex, 1);
}
// 删除array中的元素,本身就是对array数组的修改,所以此步骤必须进行
splice.call(array, fromIndex, 1);
}
}
return array;
}
function copyArray(source, array)
@param {Array} source The array to copy values from.
要从中复制值的数组
@param {Array} [array=[]] The array to copy values to.
要将值复制到的数组
function copyArray(source, array) {
// 循环的起始下标
var index = -1,
// 资源数组的数组长度
length = source.length;
// 若第一个参数存在,则保留原本,若不存在,则创建一个资源数组相同长度空数组
array || (array = Array(length));
// 遍历
while (++index < length) {
// 资源数组的当前内容赋值给拷贝数组
array[index] = source[index];
}
// 返回拷贝好的数组
return array;
}
function baseUnary(func)
unary
创建一个最多接受一个参数的函数,忽略多余的参数。baseUnary
是_.unary
的基本实现,不支持存储元数据。
function baseUnary(func) {
// 闭包返回一个新函数,这个函数可以接收一个参数
return function(value) {
// 这个闭包返回的函数再调用最外层baseUnary接收的函数参数,该函数参数拿到第一次闭包时传入的参数
return func(value);
};
}
比如
_.map(['6', '8', '10'], _.unary(parseInt));
// => [6, 8, 10]
function arrayMap(array, iteratee)
不支持迭代简写的数组的 _.map 专用版本。
众所周知,数组中的 map 方法是用于修改数组中参数内容的,也叫做映射
function arrayMap(array, iteratee) {
// 循环初始下标
var index = -1,
// 数组长度拿取
length = array == null ? 0 : array.length,
// 创建一个固定长度的新数组
result = Array(length);
// 遍历数组,若数组为空或非数组,该循环不成立,返回所有值为undefined的新数组
while (++index < length) {
// 新数组当前下标赋值
// 结合basePullAll中调用arrayMap时传入的baseUnary方法,此时iteratee是basePullAll中的一个参数,而该参数必须是一个函数
// 具体该函数应该是什么?并且返回什么?要看传入的方法是什么
result[index] = iteratee(array[index], index, array);
}
return result;
}
网友评论