Lodash 核心 Lang

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 中作了以下几个处理

  1. isObjectLike 像是一个对象
  2. 是否有 callee 属性
  3. 并且判断 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 == NaNNaN === 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 就是下面两个东西:

  1. 算术运算返回一个未定义的或无法表示的值时,NaN 就产生了
  2. 将某些不能强制转换为数值的非数值转换为数值的时候,也会得到 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 将下面几种视为空:

  1. 一个没有可以枚举属性的对象
  2. 一个 length 为 0 的 arguments||空数组||缓冲区|| 字符串 || jQuery 对象集合
  3. size 为 0 的 map || set
  4. 函数始终为空
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

  1. Function.length 作为 Function 构造器的 length 属性,始终为 1,且不可枚举
  2. Function.prototype.length 函数的形参个数
  3. 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
    1. x 或 y 其中一个是 NaN 返回 false
    2. 如果相等返回 true
    3. -0+0, +0-0 true
    4. 其他情况一律返回 false
    • 当 x 为 String
    1. x 与 y 索引上的每一位都相等,则返回 true
    2. 其它一律 false
    • 当 x 为 Boolean
    1. x 与 y 除非都为 true 或 false, 返回 true
    2. 其它一律 false
    • 当 x 为 Symbol, 只有自己和自己相等
    • 当 x 为 Object, 只有自己和自己相等
    • 其它情况一律 false
  • SameValue

    • 如果类型不同返回 false
    • x 为 undefined 或 null 返回 true
    • 当 x 为 Number
    1. x 与 y 都为 NaN 为相等
    2. -0+0, +0-0 返回 false
    3. 数值一样返回 true
    4. 其它情况一律 false
    • 当 x 为 String, x 与 y 索引上的每一位都相等,则返回 true
    • 当 x 为 Boolean,x 与 y 除非都为 true 或 false, 返回 true
    • 当 x 为 Symbol, 只有自己和自己相等
    • 当 x 为 Object, 只有自己和自己相等
  • SameValueZero

    • 如果类型不同返回 false
    • x 为 undefined 或 null 返回 true
    1. x 与 y 都为 NaN 为相等
    2. -0+0, +0-0 true
    3. 数值相等返回 true
    4. 其它一律 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))
}

参考链接

  • Lodash eq
  • MDN NaN

你可能感兴趣的:(js,js#lodash)