携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
前言
本篇章主要讲解lodash里的三个内部方法,分别为isKey、isKeyable和isTypeArray,其中isTypeArray方法在实现上会借助内部封装的几个方法,在这里我们也会顺带讲解其源码实现。
isKey
isKey方法是lodash里内部使用的方法,该方法主要是检查参数value是否是属性名称而不是属性路径。
传参说明:
第一个参数为value,第二个参数为查询键的对象。如果 value 是属性名称,则返回 true,否则返回 false。
使用说明:
isKey('a')
// => true
isKey('a.b')
// => false
isKey('a?.b')
// => false
isKey('a!.b')
// => false
isKey("a?.b!.c")
// => false
该方法在实现上借助isArray 方法判断键值value是否属于非数组,而isSymbol则判断键值value是否属于symbol类型的数据。
第一个参数value作为键值可以是number类型、symbol类型、boolean类型、或者可为null,一般情况第一个参数value可为string类型,但是为了排除是链式调用的情况,即排除属性路径,所以需要对参数value进行正则判断。
reIsDeepProp 匹配链式调用的字符串,而reIsPlainProp 则是匹配以单词开头和结尾的有效值。
源码如下:
import isArray from './isArray.js';
import isSymbol from './isSymbol.js';
var reIsDeepProp = /.|[(?:[^[]]*|(["'])(?:(?!\1)[^\]|\.)*?\1)]/,
reIsPlainProp = /^\w*$/;
function isKey(value, object) {
if (isArray(value)) {
return false;
}
var type = typeof value;
if (type == 'number' || type == 'symbol' || type == 'boolean' ||
value == null || isSymbol(value)) {
return true;
}
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
(object != null && value in Object(object));
}
isKeyable
isKeyable方法主要是检查参数value 是否适合用作唯一对象键。isKeyable方法在使用上比isKey方法宽松,对于形如链式调用的字符串属于合法的范围。
使用如下:
isKeyable('a')
// => true
isKeyable()
// => false
isKeyable([])
// => false
isKeyable('a.b')
// => true
isKeyable('a?.b')
// => true
isKeyable在是实现上使用typeof,对于string、number、symbol、boolean、null等基本数据类型验证通过,但是对于string类型,其值不能等于__proto__,因为由于原型链查找,该属性会覆盖查找。
源码如下:
function isKeyable(value) {
var type = typeof value;
return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
? (value !== '__proto__')
: (value === null);
}
isTypeArray
isTypeArray方法是内部使用的方法,该方法主要是检查参数value是否为类型化的数组。
使用如下:
_.isTypedArray(new Uint8Array);
// => true
_.isTypedArray([]);
// => false
_.isTypedArray({})
// => false
该方法实现上需要借助内部封装的baseIsTypedArray方法、baseUnary方法和nodeUtil变量。 让我们先看看各个工具方法的实现。
baseIsTypedArray
baseIsTypedArray方法是isTypeArray方法的核心,内部实现需要借助baseGetTag方法获取数据的类型标签,需要借助isLength方法判断目标数据的length是否属于有效的长度,通过isObjectLike方法判断目标数据是否属于类对象。
在实现上,通过声明各种类型标签去判断。 源码如下:
import baseGetTag from './_baseGetTag.js';
import isLength from './isLength.js';
import isObjectLike from './isObjectLike.js';
var argsTag = '[object Arguments]',
arrayTag = '[object Array]',
boolTag = '[object Boolean]',
dateTag = '[object Date]',
errorTag = '[object Error]',
funcTag = '[object Function]',
mapTag = '[object Map]',
numberTag = '[object Number]',
objectTag = '[object Object]',
regexpTag = '[object RegExp]',
setTag = '[object Set]',
stringTag = '[object String]',
weakMapTag = '[object WeakMap]';
var arrayBufferTag = '[object ArrayBuffer]',
dataViewTag = '[object DataView]',
float32Tag = '[object Float32Array]',
float64Tag = '[object Float64Array]',
int8Tag = '[object Int8Array]',
int16Tag = '[object Int16Array]',
int32Tag = '[object Int32Array]',
uint8Tag = '[object Uint8Array]',
uint8ClampedTag = '[object Uint8ClampedArray]',
uint16Tag = '[object Uint16Array]',
uint32Tag = '[object Uint32Array]';
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;
function baseIsTypedArray(value) {
return isObjectLike(value) &&
isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}
isTypeArray
借助封装的baseIsTypedArray方法即可实现isTypedArray方法,为了兼容不同环境下的方法调用,通过nodeUtil变量判断宿主环境并获取node环境工具方法中的isTypedArray方法,通过baseUnary的调用返回一个新的函数方法。
import baseIsTypedArray from './_baseIsTypedArray.js';
import baseUnary from './_baseUnary.js';
import nodeUtil from './_nodeUtil.js';
var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
小结
本篇章我们主要讲解isKey、isKeyable和isTypeArray方法,其中通过isTypeArray方法我们认识了baseUnary方法、nodeUtil变量以及核心实现baseIsTypedArray方法。
可见lodash为了兼容版本以及环境,内部做了多数封装和的兼容判断。