by @zhangbao(zhangbao) #0105javascript
什么是类数组呢?查看 Lodash _.isArrayLike(value)
函数的实现,得知参数 value
须符合下列条件:java
length
属性length
属性值是不大于 Number.MAX_SAFE_INTEGER
的天然数字符串就符合这个条件,说明它就是类数组。git
著名 JS 工具库 Lodash 提供了一个工具函数:_.isArrayLike(value)
,检查某个值是否为类数组的。下面是官方给的用例:github
_.isArrayLike([1, 2, 3]);
// => true
_.isArrayLike(document.body.children);
// => true
_.isArrayLike('abc');
// => true
_.isArrayLike(_.noop);
// => false
复制代码
_.isArrayLike
的实现细节下面是定义函数 isArrayLike
的地方:数组
import isLength from './isLength.js'
function isArrayLike(value) {
return value != null && typeof value !== 'function' && isLength(value.length)
}
复制代码
首先检查输入的值:函数
value != null
:这个判断使用的是 !=
,而非 !==
。令判断结果为 false
的值有两个:null
和 undefined
。就是说,若是向 isArrayLike
函数传入的值是 null
或 undefined
,那么第一个判断都未知足,直接返回 false
。💡 提示: 这里引入了 JS 一个小怪癖的地方,就是规范中定义对于抽象相等算法(
==
内部执行的就是此算法):null == undefined
比较结果返回true
,天然null != undefined
的返回结果为false
。工具
typeof value !== 'function'
:传入值不能是函数,若是函数的话,也不算是类数组。isLength(value.length)
:最后检查传入值的 length
属性,isLength(value.length)
返回值即 isArrayLike
的返回值。isLength
函数是用来干什么的?咱们来看下:oop
const MAX_SAFE_INTEGER = 9007199254740991
/** * Checks if `value` is a valid array-like length. * * **Note:** This method is loosely based on * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * ... * */
function isLength(value) {
return typeof value === 'number' &&
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER
}
复制代码
根据注释,咱们知道 isLength
函数是用来检查传入值 value
是否为有效长度。这里的 MAX_SAFE_INTEGER
就等于 Number.MAX_SAFE_INTEGER
的值,这样写的目的估计是为了效率,能少一步计算。ui
根据判断逻辑,咱们知道所谓“有效的长度值”,是指值不大于 Number.MAX_SAFE_INTEGER
的天然数。
好比如下这些值,就不能算是有效的长度值:
isLength(Number.MIN_VALUE)
// => false。负数不是
isLength(Infinity)
// => false。无穷大不是
isLength('3')
// => false。字符串也不是
复制代码
根据 isLength
方法的注释说明:此种验证方式是对规范中定义的抽象算法 ToLength
的宽松实现。下面是规范中的定义:
相较于规范中的定义,后者是包含类型转换和参数值纠正逻辑的:
ToInteger(argument)
)+0
;无穷大转为 253 - 1 等。而这在 Lodash 中的实现中是没有的,这就是为何称之为“宽松实现”的缘由。
(完)