摘要:写了几篇笔记以后发现很多函数大量依赖了内部的基础函数,一次性读完有点麻烦,所以还是决定从基础函数没有或者很少依赖其他函数看起。
百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。写了几篇笔记以后发现很多函数大量依赖了内部的基础函数,一次性读完有点麻烦,所以还是决定从基础函数(没有或者很少依赖其他函数)看起。
文档地址:中文文档 英文文档
源码地址:gayhub
baseGetTag,判断变量类型。因为typeof在面对new Number(1)这种情况时力有不逮,所以lodash重写了类型判断。 javascript秘密花园中也提到了JavaScript 标准库 推荐的是Object.prototype.toString.call(value)这种方式来判断类型,不过lodash明显做的更多,前半段是推荐的方式,后半段目测是针对Symbol类型做了优化,具体步骤待研究,有了解的同学欢迎告诉我。
const objectProto = Object.prototype const hasOwnProperty = objectProto.hasOwnProperty const toString = objectProto.toString const symToStringTag = typeof Symbol != "undefined" ? Symbol.toStringTag : undefined function baseGetTag(value) { if (value == null) { return value === undefined ? "[object Undefined]" : "[object Null]" } if (!(symToStringTag && symToStringTag in Object(value))) { return toString.call(value) } const isOwn = hasOwnProperty.call(value, symToStringTag) const tag = value[symToStringTag] let unmasked = false try { value[symToStringTag] = undefined unmasked = true } catch (e) {} const result = toString.call(value) if (unmasked) { if (isOwn) { value[symToStringTag] = tag } else { delete value[symToStringTag] } } return result } export default baseGetTaggetTag
getTag是在baseGetTag基础上的包装,主要是为了兼容IE 11中的 data views, maps, sets, weak maps 和当Node.js < 6时的promises,这一点在源码注释中已有体现
import baseGetTag from "./baseGetTag.js" /** `Object#toString` result references. */ const dataViewTag = "[object DataView]" const mapTag = "[object Map]" const objectTag = "[object Object]" const promiseTag = "[object Promise]" const setTag = "[object Set]" const weakMapTag = "[object WeakMap]" /** Used to detect maps, sets, and weakmaps. */ const dataViewCtorString = `${DataView}` const mapCtorString = `${Map}` const promiseCtorString = `${Promise}` const setCtorString = `${Set}` const weakMapCtorString = `${WeakMap}` let getTag = baseGetTag // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in // Node.js < 6. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (getTag(new Map) != mapTag) || (getTag(Promise.resolve()) != promiseTag) || (getTag(new Set) != setTag) || (getTag(new WeakMap) != weakMapTag)) { getTag = (value) => { const result = baseGetTag(value) const Ctor = result == objectTag ? value.constructor : undefined const ctorString = Ctor ? `${Ctor}` : "" if (ctorString) { switch (ctorString) { case dataViewCtorString: return dataViewTag case mapCtorString: return mapTag case promiseCtorString: return promiseTag case setCtorString: return setTag case weakMapCtorString: return weakMapTag } } return result } } export default getTagisObjectLike
isObjectLike, 判断是否是一个对象
function isObjectLike(value) { return typeof value == "object" && value !== null } export default isObjectLikeisArguments
isArguments调用了getTag和isObjectLike用来判断参数是否是一个Arguments对象。
import getTag from "./.internal/getTag.js" import isObjectLike from "./isObjectLike" function isArguments(value) { return isObjectLike(value) && getTag(value) == "[object Arguments]" } export default isArgumentsisFlattenable
isFlattenable调用isArguments来判断是否为一个Arguments对象或数组或是一个能展开的Symbol
import isArguments from "../isArguments.js" const spreadableSymbol = Symbol.isConcatSpreadable function isFlattenable(value) { return Array.isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]) } export default isFlattenablebaseFlatten
baseFlatten可以展开数组的n层嵌套(扁平处理),依赖了isFlattenable
// 例: baseFlatten([[[1,2,3],[2,2,3]],4,5,6], 2) // => [1, 2, 3, 2, 2, 3, 4, 5, 6] // isStrict == true baseFlatten([[1,2,3],[2,2,3],4,5,6], 1, null, true) // => [1, 2, 3, 2, 2, 3]
import isFlattenable from "./isFlattenable.js" function baseFlatten(array, depth, predicate, isStrict, result) { predicate || (predicate = isFlattenable) // predicate参数兜底 result || (result = []) // 返回新数组 if (array == null) { return result } // 递归调用本身,严格模式`isStrict = true`直接退出循环 for (const value of array) { if (depth > 0 && predicate(value)) { if (depth > 1) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, depth - 1, predicate, isStrict, result) } else { result.push(...value) } } else if (!isStrict) { result[result.length] = value } } return result } export default baseFlattenisLength
isLength,判断是否是一个有效数字
const MAX_SAFE_INTEGER = 9007199254740991 // 最大数 function isLength(value) { // type是number并且大于等于0且小于等于最大数 return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER } export default isLengthisArrayLike
isArrayLike, 判断是否是一个数组,依赖了isLength
import isLength from "./isLength.js" function isArrayLike(value) { // value不为空,不是function且有length属性 return value != null && typeof value != "function" && isLength(value.length) } export default isArrayLikeisArrayLikeObject
isArrayLikeObject,判断是否是一个数组或者对象,依赖了isArrayLike和isObjectLike
import isArrayLike from "./isArrayLike.js" import isObjectLike from "./isObjectLike.js" function isArrayLikeObject(value) { return isObjectLike(value) && isArrayLike(value) } export default isArrayLikeObjecteq
eq,判断两个值是否相等。
function eq(value, other) { return value === other || (value !== value && other !== other) } export default eq
||前面好理解,判断两个值全等
||后面是为了判断 NaN
例:
const object = { "a": 1 } const other = { "a": 1 } eq(object, object) // => true eq(object, other) // => false eq("a", "a") // => true eq("a", Object("a")) // => false eq(NaN, NaN) // => trueassocIndexOf
获取键值对数组中的“键”的索引。例:
assocIndexOf([[1,2],[3,4],[5,6]], 2) // => -1 assocIndexOf([[1,2],[3,4],[5,6]], 3) // => 1
import eq from "../eq.js" function assocIndexOf(array, key) { let { length } = array while (length--) { if (eq(array[length][0], key)) { return length } } return -1 } export default assocIndexOf
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/93536.html
摘要:是函数柯里化的函数。例子柯里化有个常见作用参数复用构建高阶函数延迟计算。是的,它其实就是柯里化的具体应用构建高阶函数。这个是我认为的中最有意思的方法。不过要注意最后的。这同样是用来组合高阶函数的一个方法。 最近在学习JS函数式编程相关的内容,于是详细的翻看了Lodash的文档,感到别有洞天。这里把自己对一些API的使用和看法做个笔记记录下。 Array _.head/_.last 例子...
摘要:例如现在的入门学习手记系列。收到粉丝留言和打赏的喜悦。安装上一篇入门学习手记一,主要是介绍了的核心概念,是整个学习过程的基础知识。新生成的类似如下入门学习手记因为生成的内容过多,我直接省略掉了。 showImg(https://segmentfault.com/img/bVbk5Nd?w=1150&h=599); 本人微信公众号:前端修炼之路,欢迎关注。 最近开始想要维护一个个人的公众...
摘要:文档地址中文文档英文文档源码地址将数组拆分成多个长度的区块,并将这些区块组成一个新数组。如果无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源码地址:gayhub _.chunk(array, [size...
摘要:文档地址中文文档英文文档源码地址创建一个新数组,包含原数组中所有的非假值元素。例如和都是被认为是假值。下面对比一下两者效率,如下图传送门可以看到使用更快,如果没有兼容性需求,还是使用原生函数比较好。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源码地址:gayhub ...
摘要:文档地址中文文档英文文档源码地址第一个函数是,不过源码中依赖了,所以第一篇文章就从开始。这个函数的作用就是裁剪数组,从下标开始,到下标结束,但是并不包含,并将结果作为一个数组返回。并且注明了这个方法用于代替来确保数组正确返回。 百忙之中(闲来无事)想抽点时间好好读一下源码,于是就选了Lodash来写一个系列罢。读源码顺序就按照loadsh文档顺序来。 文档地址:中文文档 英文文档源...
阅读 464·2023-04-25 23:00
阅读 3495·2021-11-22 13:54
阅读 1897·2021-10-27 14:14
阅读 1485·2019-08-30 13:59
阅读 3512·2019-08-23 16:15
阅读 1959·2019-08-23 16:06
阅读 3326·2019-08-23 15:26
阅读 1258·2019-08-23 13:48