

硬刚 lodash 源码之路,_.chunk
source link: http://www.cnblogs.com/guangzan/p/13233111.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前置
chunk
函数内部借助其他函数实现,所以从其他函数开始, chunk
在最后。
你可能需要一些 JavaScript 基础知识才能看懂一些没有注释的细节。
isObject
判断是否为 Object 类型
/** * Checks if `value` is the * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * isObject({}) * // => true * * isObject([1, 2, 3]) * // => true * * isObject(Function) * // => true * * isObject(null) * // => false */ function isObject(value) { const type = typeof value // 将 function 作为 Object 类型 return value != null && (type === 'object' || type === 'function') } export default isObject
getTag
getTag 获取给定值的 toStringTag
。
Symbol.toStringTag
是一个内置 symbol,它通常作为对象的属性键使用,对应的属性值应该为字符串类型,这个字符串用来表示该对象的自定义类型标签,通常只有内置的 Object.prototype.toString()
方法会去读取这个标签并把它包含在自己的返回值里。
许多内置的 JavaScript 对象类型即便没有 toStringTag
属性,也能被 toString()
方法识别并返回特定的类型标签,比如:
Object.prototype.toString.call('foo'); // "[object String]" Object.prototype.toString.call([1, 2]); // "[object Array]" Object.prototype.toString.call(3); // "[object Number]" Object.prototype.toString.call(true); // "[object Boolean]" Object.prototype.toString.call(undefined); // "[object Undefined]" Object.prototype.toString.call(null); // "[object Null]" // ... and more
另外一些对象类型则不然, toString()
方法能识别它们是因为引擎为它们设置好了 toStringTag
标签:
Object.prototype.toString.call(new Map()); // "[object Map]" Object.prototype.toString.call(function* () {}); // "[object GeneratorFunction]" Object.prototype.toString.call(Promise.resolve()); // "[object Promise]" // ... and more
对于你自己创建的类, toString()
找不到 toStringTag
属性时只好返回默认的 Object 标签:
class ValidatorClass {} Object.prototype.toString.call(new ValidatorClass()); // "[object Object]"
加上 toStringTag
属性,你的类也会有自定义的类型标签了:
class ValidatorClass { get [Symbol.toStringTag]() { return "Validator"; } } Object.prototype.toString.call(new ValidatorClass()); // "[object Validator]"
const toString = Object.prototype.toString /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function getTag(value) { // 处理 value 能够转化为 null 的值 if (value == null) { return value === undefined ? '[object Undefined]' : '[object Null]' } return toString.call(value) } export default getTag
isSymbol
_.isSymbol(value)
检查 value 是否是 原始 Symbol 或者对象 。
import getTag from './.internal/getTag.js' /** * Checks if `value` is classified as a `Symbol` primitive or object. * * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. * @example * * isSymbol(Symbol.iterator) * // => true * * isSymbol('abc') * // => false */ function isSymbol(value) { // typeof 比 Object.prototype.toString 效率高 const type = typeof value return type == 'symbol' || (type === 'object' && value != null && getTag(value) == '[object Symbol]') } export default isSymbol
toNumber
_.toNumber(value)
转换 value 为一个 数字 。
import isObject from './isObject.js' import isSymbol from './isSymbol.js' /** Used as references for various `Number` constants. */ const NAN = 0 / 0 /** Used to match leading and trailing whitespace. */ const reTrim = /^\s+|\s+$/g /** Used to detect bad signed hexadecimal string values. */ // 用于检测错误的有符号十六进制字符串值 const reIsBadHex = /^[-+]0x[0-9a-f]+$/i /** Used to detect binary string values. */ // 二进制。 const reIsBinary = /^0b[01]+$/i /** Used to detect octal string values. */ // 八进制 const reIsOctal = /^0o[0-7]+$/i /** Built-in method references without a dependency on `root`. */ // 不依赖于 root 的内置方法引用 // 防止全局作用域下的parseInt被用户替换 const freeParseInt = parseInt /** * Converts `value` to a number. * * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @see isInteger, toInteger, isNumber * @example * * toNumber(3.2) * // => 3.2 * * toNumber(Number.MIN_VALUE) * // => 5e-324 * * toNumber(Infinity) * // => Infinity * * toNumber('3.2') * // => 3.2 */ function toNumber(value) { if (typeof value === 'number') { return value } if (isSymbol(value)) { return NAN // Number 的引用 } // Object.prototype.valueOf() 方法返回指定对象的原始值 // 默认情况下,valueOf方法由Object后面的每个对象继承。 // 每个内置的核心对象都会覆盖此方法以返回适当的值。 // 如果对象没有原始值,则valueOf将返回对象本身。 if (isObject(value)) { // value 没有 valueOf 函数或者 valueOf 函数返回一个对象, // 将 other 转换成 string 类型,留待后面处理。 const other = typeof value.valueOf === 'function' ? value.valueOf() : value value = isObject(other) ? `${other}` : other } if (typeof value !== 'string') { return value === 0 ? value : +value } // @example // const a = function() {} // console.log(a.valueOf()); // -> [Function: a] // console.log(typeof a.valueOf()); // -> function // @example // const a = {} // console.log(a.valueOf(); // -> {} // 16进制返回NAN // 10进制数(+)确保返回值是数值类型 value = value.replace(reTrim, '') // 用''替换掉字符串中符合reTrim的项 const isBinary = reIsBinary.test(value) // 二进制 return (isBinary || reIsOctal.test(value)) // 二进制或八进制 ? freeParseInt(value.slice(2), isBinary ? 2 : 8) // 删除字符串前两位并解析为十进制的整数 : (reIsBadHex.test(value) ? NAN : +value) // 十六进制字符串值返回 NAN,否则返回十进制(+) } export default toNumber
toFinite
_.toFinite(value)
转换 value 为一个 有限数字 。
import toNumber from './toNumber.js' /** Used as references for various `Number` constants. */ const INFINITY = 1 / 0 // 无穷 const MAX_INTEGER = 1.7976931348623157e+308 // 最大整数 /** * Converts `value` to a finite number. * * @since 4.12.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted number. * @example * * toFinite(3.2) * // => 3.2 * * toFinite(Number.MIN_VALUE) * // => 5e-324 * * toFinite(Infinity) * // => 1.7976931348623157e+308 * * toFinite('3.2') * // => 3.2 */ function toFinite(value) { // undefined & null -> 0 if (!value) { return value === 0 ? value : 0 } value = toNumber(value) // 正负无穷取正负最大值 if (value === INFINITY || value === -INFINITY) { const sign = (value < 0 ? -1 : 1) return sign * MAX_INTEGER } return value === value ? value : 0 } export default toFinite
toInteger
_.toInteger(value)
转换 value 为一个 整数 。
import toFinite from './toFinite.js' /** * Converts `value` to an integer. * * **Note:** This method is loosely based on * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). * * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @see isInteger, isNumber, toNumber * @example * * toInteger(3.2) * // => 3 * * toInteger(Number.MIN_VALUE) * // => 0 * * toInteger(Infinity) * // => 1.7976931348623157e+308 * * toInteger('3.2') * // => 3 */ function toInteger(value) { const result = toFinite(value) // result 为小数时,则 remainder 不为 0 const remainder = result % 1 // 余数 // 抹掉小数位 return remainder ? result - remainder : result } export default toInteger
chunk
_.chunk(array, [size=1])
将数组 拆分 成多个 size 长度的区块,并将这些区块组成一个新数组。 如果array 无法被分割成全部等长的区块,那么最后剩余的元素将组成一个区块。
import slice from './slice.js' import toInteger from './toInteger.js' /** * @since 3.0.0 * @category Array * @param {Array} array The array to process. * @param {number} [size=1] The length of each chunk * @returns {Array} Returns the new array of chunks. * @example * * chunk(['a', 'b', 'c', 'd'], 2) * // => [['a', 'b'], ['c', 'd']] * * chunk(['a', 'b', 'c', 'd'], 3) * // => [['a', 'b', 'c'], ['d']] */ function chunk(array, size = 1) { // 令 size >= 0 size = Math.max(toInteger(size), 0) const length = array == null ? 0 : array.length if (!length || size < 1) { return [] } // 构建新数组 let index = 0 let resIndex = 0 const result = new Array(Math.ceil(length / size)) while (index < length) { result[resIndex++] = slice(array, index, (index += size)) } return result } export default chunk
参考资料:MDN
Recommend
-
60
前言 lodash受欢迎的一个原因,是其优异的计算性能。而其性能能有这么突出的表现,很大部分就来源于其使用的算法——惰性求值。 本文将讲述lodash源码中,惰性求值的原理和实现。 一、惰性求值的原理分析 惰性求值(Lazy Evaluation),又译为惰
-
56
这世界上之所以会有无主的东西,方法是因为有人失去了记忆。 ——王小波《万寿寺》 本文为读 lodash 源码的第二十篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash gitbook也会同步仓库的更新,gitbook地址:pocket
-
18
Earth ScienceA Large Chunk of Ice Has Torn Away From Menacing Iceberg A68aMODIS satellite image showing the new iceberg fragment. Image: Ste...
-
10
学习 lodash 源码整体架构,打造属于自己的函数式编程类库若川公众号:若川视野 微信:ruochuan12
-
10
array_chunk in PHP By continuing your visit to this site, you accept the use of cookies. Read more. Scout APM helps PHP developers pin...
-
13
Laravel Eloquent chunk () 与 chunkyById () 的区别Summer摈弃世俗浮躁,追求技术精湛
-
13
鲁迅说过:只有阅读过优秀库源码的人,才能配的上是真正的勇士。 compact 创建一个新数组,包含原数组中所有的非假值元素。例如false, null,0, “”, undefined, 和 NaN 都是被认为是“假值”。 注意...
-
7
一、chunk简介 1.1 chunk是什么 MongoDB在Sharding模式下(对于Sharding不了解的可以参考shard介绍),通过Mongos向开启了shard分片的集合写入文档,这些文档会根据其shardKey分散...
-
5
时序数据库Influx-IOx源码学习八(Chunk持久化) - 刘涛华的个人空间 - OSCHINA - 中文开源技术交流社区 仅限深圳|现场揭秘:腾讯云原生数据...
-
6
chunk extend overlapping在堆中是一种比较常见的利用手段,其主要原理就是因为某些意外情况我们可以去修改一些已经申请或在空闲状态的堆块的大小,从而造成堆块重叠的情况,而这也就引发了一系列安全隐患。 本文涉及相关实验:
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK