A modern JavaScript utility library delivering modularity, performance & extras.
是一个一致性、模块化、高性能的 JavaScript 实用工具库。
借网上的一个总结, Lodash 提供的函数主要分为以下几类:
- Array,适用于数组类型,比如填充数据、查找元素、数组分片等操作
- Collection,适用于数组和对象类型,部分适用于字符串,比如分组、查找、过滤等操作
- Function,适用于函数类型,比如节流、延迟、缓存、设置钩子等操作
- Lang,普遍适用于各种类型,常用于执行类型判断和类型转换
- Math,适用于数值类型,常用于执行数学运算
- Number,适用于生成随机数,比较数值与数值区间的关系
- Object,适用于对象类型,常用于对象的创建、扩展、类型转换、检索、集合等操作
- Seq,常用于创建链式调用,提高执行性能(惰性计算)
- String,适用于字符串类型
Lodash.isArguments
判断是否是一个 arguments 对象, arguments 也就是函数参数对象, 是数组的一种鸭子类型, 该对象有两个特点, 一就是 typeof 操作符会返回 object 并且有 callee 属性,lodash 中作了以下几个处理
- isObjectLike 像是一个对象
- 是否有 callee 属性
- 并且判断 callee 不可枚举
function _isArguments(value) {
return value != null && typeof value == 'object' &&
value.hasOwnProperty('callee') &&
!value.propertyIsEnumerable('callee');
}
Lodash.isFunction
判断是否是一个函数,其中 lodash 对 AsyncFunction,Function,GeneratorFunction 三种函数都作了判断
function* gen1(){}
async function getData(){}
function bar () {}
console.log(({}).toString.call(gen1) ) // [object GeneratorFunction]
console.log(({}).toString.call(getData) ) // [object AsyncFunction]
console.log(({}).toString.call(bar) ) // [object Function]
Lodash.isObject
lodash 将非 null 值,普通对象和函数都当作对象,而isObjectLike只是除开了函数
function _isObject(value) {
var type = typeof value;
return value != null && (type == 'object' || type == 'function');
}
console.log(typeof null) // object
console.log(typeof ({})) // object
console.log(_isObject(null) ) // false
console.log(_isObject({}) ) // true
Lodash.isNumber
lodash 有点类似恒等于于数字,但 lodash 并没有直接用恒等于,而是和 isFunction 一样,用了 toString 将字符数值和普通数字区分开来
function _isNumber(value) {
return typeof value == 'number' ||
(isObjectLike(value) && baseGetTag(value) == numberTag);
}
Lodash.isNaN
Lodash 这个方法可以说是一个比较有趣的方法, Lodash 检测一个值是否是一个非数字是基于 Number.isNaN 并非全局下的 isNaN
并且 isNaN 还比较诡异
Lodash 的 isNaN 说明为:如果 value 是一个 NaN,那么返回 true,否则返回 false
Global.isNaN
全局下的 isNaN 与中其他的值不同,NaN 不能通过相等操作符 == || === 来判断 ,因为 NaN == NaN 和 NaN === NaN 都会返回 false
NaN 是什么? 千万不要以先入为主的思想去把 NaN 当作不是一个数字来看待,因为不是一个数字的类型在 JavaScript 中太多了,就比如一个{},一个/\d/,一个[]太多太多了,如果这些都是 NaN 那么难道 NaN 表示的就是一个不是一个数字的意思吗?那这就是一个错的
// 这几个会隐式的将不是数字的操作数转换成数字计算
console.log( 1 + 1) // 2
console.log( false + 1) // 1
console.log( 1 + []) // 1
// 下面那个会隐式的调用自己的 toString,结果就会将变成字符串连接
console.log( {} + 1) // [object Object]1
console.log( /\d/ + 1) // /\d/1
那 NaN 到底是一个什么呢? 借 MDN 一句话,NaN 就是下面两个东西:
- 算术运算返回一个未定义的或无法表示的值时,NaN 就产生了
- 将某些不能强制转换为数值的非数值转换为数值的时候,也会得到 NaN
但是,NaN并不一定用于表示某些值超出表示范围的情况
先看什么是无法表示的值,首先未定义从字面意思也能理解,在 JavaScript 中就是 undefined 嘛
console.log( undefined + 1) //=> NaN
算术运算符 + 将 undefined 和 1 相加时会隐式转换成数字与右操作数相加, 在隐式转换的时候 undefined 本身是没有 toString 或者是 valueOf 方法的,也就无法完成运算符 + 的运算,这个结果对于 JavaScript 那就是一个不能用任何可以得到的结果表示,那这个结果只能是 NaN 了
其二不能被强制转换成数字的类型被转换成数字类型那结果也是 NaN
console.log( Number(undefined) ) //=> NaN
console.log( Number(false) ) //=> 0
console.log( Number({}) ) //=> NaN
console.log( Number(/\d/) ) //=> NaN
console.log( Number('a2b') ) //=> NaN
console.log( Number('') ) //=> 0
上述中可以看出很多种情况在做强制转换的时候都会返回 NaN,还有一种则是某些值超出了范围
console.log(0 / 0 ) //=> NaN
而对于全局的 isNaN 方法来说,会首先尝试将这个参数转换为数值,然后才会对转换后的结果是否是 NaN 进行判断,也许看到这里也会不明白上面为什么或那里有问题,为什么诡异,我看到这里的时候也是如此,那么先带着疑惑看看 Number.isNaN
JavaScript 中只有 NaN 不等于或不恒等于自身
Number.isNaN
同样借 MDN 一句话,注意,这里的中文文档个人觉得翻译有误,中文文档翻译的是 “确定传递的值是否为 NaN和其类型是 Number” 有点像中式英语,人个觉得就里翻译成确定传递的值是否为 Number 类型的 NaN
该方法不会强制将参数转换成数字,只有在参数是真正的数字类型,且值为 NaN 的时候才会返回 true
注意, MDN 上解释到参数只有是数字类型,且为 NaN 的时候才表示为 NaN,为什么会这样呢?我也是突然看见了这么一个例子才恍然大悟
function typeOfNaN(x) {
if (Number.isNaN(x)) {
return 'Number NaN';
}
if (isNaN(x)) {
return 'NaN';
}
}
console.log(typeOfNaN('100F')) //=>"NaN"
console.log(typeOfNaN(NaN)) //=>"Number NaN"
其实什么全局的 isNaN 也好,还是ES5 加强后的 Number.isNaN 或者是 NaN 本身,理解 NaN 是什么,从什么角度才是最重要的,全局上理解 NaN 则可以看作是一个其是否是一个可以被转换成数字类型的值,从 ES5 加强后的可以看作是一个其是否是一个可以非数字的数值类型的值
Number.isNaN 则是将需要判断数值 value 是 NaN 那么返回 true,否则返回 false,这样就可以避免掉使用全局的在理解上的混淆, lodash 我想也是因为这样的吧
Lodash.isEmpty
Lodash 将下面几种视为空:
- 一个没有可以枚举属性的对象
- 一个 length 为 0 的
arguments||空数组||缓冲区|| 字符串 || jQuery 对象集合 - size 为 0 的 map || set
- 函数始终为空
console.log( Lodash.isEmpty(null) ) // => true
console.log( Lodash.isEmpty(true) ) // => true
console.log( Lodash.isEmpty('1') ) // => false
console.log( Lodash.isEmpty(1) ) // => true
console.log( Lodash.isEmpty([1, 2, 3]) ) // => false
console.log( Lodash.isEmpty({ 'a': 1 }) ) // => false
需要注意的是,三个 length
- Function.length 作为 Function 构造器的 length 属性,始终为 1,且不可枚举
- Function.prototype.length 函数的形参个数
- argument.length 函数的实参个数
console.log( Function.length ) //=> 1
console.log( function(){}.length ) //=> 0
console.log( function(a,b){}.length ) //=> 2
console.log( (function(a,b){ return arguments.length}(1)) ) //=> 1
console.log( ((a,b,c)=>{}).length ) //=> 3
Lodash.isEmpty 会将一个函数当作空,不管该函数有多少个形参或实参,这里说起函数下面看一个 isNative 的方法
Lodash.isNative 判断一个参数是否为原生函数
原生函数就像是数组的 join,split,push 等这类函数,也就是由 JavaScript 实现的函数,但是该方法不包括在 lodash 核心中
console.log( Lodash.isNative( Lodash.isEmpty ) ) //=> false
console.log( Lodash.isNative( [1,2,3].push ) ) //=> true
Lodash.eq
先看看 ECMAScript 规定的几个内部比较规范,可能会更好理解 eq 方法,以 x,y 两个未知数做比较有以下几可能:
- 恒等于与 SameVlue 对比多处理了有符号数和 NaN 情况 Strict Equality Comparison
- x y 两个数类型不同则为 false
- x 为 undefined 或 null 直接返回 true
- 当 x 为 Number
- x 或 y 其中一个是 NaN 返回 false
- 如果相等返回 true
-0与+0,+0与-0true- 其他情况一律返回 false
- 当 x 为 String
- x 与 y 索引上的每一位都相等,则返回 true
- 其它一律 false
- 当 x 为 Boolean
- x 与 y 除非都为 true 或 false, 返回 true
- 其它一律 false
- 当 x 为 Symbol, 只有自己和自己相等
- 当 x 为 Object, 只有自己和自己相等
- 其它情况一律 false
-
- 如果类型不同返回 false
- x 为 undefined 或 null 返回 true
- 当 x 为 Number
- x 与 y 都为 NaN 为相等
-0与+0,+0与-0返回 false- 数值一样返回 true
- 其它情况一律 false
- 当 x 为 String, x 与 y 索引上的每一位都相等,则返回 true
- 当 x 为 Boolean,x 与 y 除非都为 true 或 false, 返回 true
- 当 x 为 Symbol, 只有自己和自己相等
- 当 x 为 Object, 只有自己和自己相等
-
- 如果类型不同返回 false
- x 为 undefined 或 null 返回 true
- x 与 y 都为 NaN 为相等
-0与+0,+0与-0true- 数值相等返回 true
- 其它一律 false
- 当 x 为 Boolean,x 与 y 除非都为 true 或 false, 返回 true
- 当 x 为 Symbol, 只有自己和自己相等
- 当 x 为 Object, 只有自己和自己相等
先多说一句规范中这么多的比较规范, Lodash 使用了 SameValueZero, 仔细观察三个规范的相同处于不同处,会发现除了在数字比较时 NaN 和 -0 与 +0 比较有出处,其它地方几乎一样,也就是说,在恒等的基础上将 NaN 和 -0 与 +0 进行了多一次的判断,上面有提到一个 NaN 的特性不知道还有印象没有,说 JavaScript 中只有 NaN 不恒等自己
function _eq(value, other) {
return value === other || (value !== value && other !== other);
}
console.log( _eq(NaN, NaN) ) //=> true
console.log( _eq(-0, +0) ) //=> true
console.log( _eq(1, '1') ) //=> false
console.log( _eq(null, undefined) ) //=> false
console.log( _eq(null, {}) ) //=> false
而由于全局 isNaN 的判断诡异,如果非要利用 isNaN 则可以使用 Number.isNaN 来专门判断是否是一个非数字类型,下面例子与上面例子是恒等的
function _eq(value, other) {
return value === other || (Number.isNaN(value) && Number.isNaN(other))
}
参考链接
来源:CSDN
作者:异世界大魔王
链接:https://blog.csdn.net/oldArray/article/details/104169627