内容简介:你可能需要一些 JavaScript 基础知识才能看懂一些没有注释的细节。判断是否为 Object 类型
前置
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
以上所述就是小编给大家介绍的《硬刚 lodash 源码之路,_.chunk》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 【源码阅读】AndPermission源码阅读
- ReactNative源码解析-初识源码
- 【源码阅读】Gson源码阅读
- Spring源码系列:BeanDefinition源码解析
- istio 源码 – Citadel 源码分析 (原创)
- istio 源码 – pilot 源码分析(原创)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。