baseIsTypedArray 是 isTypedArray 在浏览器环境的默认实现。
功能概述
baseIsTypedArray 函数是 Lodash 中用于判断一个值是否为 TypedArray 类型的内部工具函数。它通过检查对象的特性、长度属性以及类型标签,来准确识别诸如 Int8Array、Float32Array 等类型化数组。
源码实现
function baseIsTypedArray(value) {
return (
isObjectLike(value) &&
isLength(value.length) &&
!!typedArrayTags[baseGetTag(value)]
);
}
实现原理解析
1. 对象特性检查
函数首先通过 isObjectLike(value) 确保传入值具有对象特性:
// 示例:基本类型值不是 TypedArray
const num = 42;
console.log(isObjectLike(num)); // false
// 示例:TypedArray 实例是对象
const int8Arr = new Int8Array(4);
console.log(isObjectLike(int8Arr)); // true
// 示例:普通数组也是对象
const arr = [1, 2, 3, 4];
console.log(isObjectLike(arr)); // true
这一步筛选掉了所有基本类型值,因为 TypedArray 必定是对象。
2. 长度属性验证
接着通过 isLength(value.length) 验证对象的 length 属性是否为有效的数组长度:
// 示例:TypedArray 的长度是有效的非负整数
const uint8Arr = new Uint8Array(3);
console.log(isLength(uint8Arr.length)); // true
// 示例:对象的数值属性不是有效长度
const obj = { length: -1 };
console.log(isLength(obj.length)); // false
// 示例:超出安全整数范围的长度无效
const invalidObj = { length: Number.MAX_SAFE_INTEGER + 1 };
console.log(isLength(invalidObj.length)); // false
这一步确保了对象具有合法的数组长度属性,是类型化数组的必要条件。
3. 类型标签匹配
最后通过 !!typedArrayTags[baseGetTag(value)] 检查对象的内部 [[Class]] 标签:
// 示例:Int8Array 的类型标签匹配
const int8Arr = new Int8Array(4);
console.log(baseGetTag(int8Arr)); // '[object Int8Array]'
console.log(!!typedArrayTags[baseGetTag(int8Arr)]); // true
// 示例:Uint8Array 的类型标签匹配
const uint8Arr = new Uint8Array(4);
console.log(baseGetTag(uint8Arr)); // '[object Uint8Array]'
console.log(!!typedArrayTags[baseGetTag(uint8Arr)]); // true
// 示例:Uint8ClampedArray 的类型标签匹配
const uint8ClampedArr = new Uint8ClampedArray(4);
console.log(baseGetTag(uint8ClampedArr)); // '[object Uint8ClampedArray]'
console.log(!!typedArrayTags[baseGetTag(uint8ClampedArr)]); // true
// 示例:Int16Array 的类型标签匹配
const int16Arr = new Int16Array(4);
console.log(baseGetTag(int16Arr)); // '[object Int16Array]'
console.log(!!typedArrayTags[baseGetTag(int16Arr)]); // true
// 示例:Uint16Array 的类型标签匹配
const uint16Arr = new Uint16Array(4);
console.log(baseGetTag(uint16Arr)); // '[object Uint16Array]'
console.log(!!typedArrayTags[baseGetTag(uint16Arr)]); // true
// 示例:Int32Array 的类型标签匹配
const int32Arr = new Int32Array(4);
console.log(baseGetTag(int32Arr)); // '[object Int32Array]'
console.log(!!typedArrayTags[baseGetTag(int32Arr)]); // true
// 示例:Uint32Array 的类型标签匹配
const uint32Arr = new Uint32Array(4);
console.log(baseGetTag(uint32Arr)); // '[object Uint32Array]'
console.log(!!typedArrayTags[baseGetTag(uint32Arr)]); // true
// 示例:Float32Array 的类型标签匹配
const float32Arr = new Float32Array(2);
console.log(baseGetTag(float32Arr)); // '[object Float32Array]'
console.log(!!typedArrayTags[baseGetTag(float32Arr)]); // true
// 示例:Float64Array 的类型标签匹配
const float64Arr = new Float64Array(2);
console.log(baseGetTag(float64Arr)); // '[object Float64Array]'
console.log(!!typedArrayTags[baseGetTag(float64Arr)]); // true
// 示例:普通数组的类型标签不匹配
const normalArr = [1, 2];
console.log(baseGetTag(normalArr)); // '[object Array]'
console.log(!!typedArrayTags[baseGetTag(normalArr)]); // false
// 示例:类数组对象的类型标签不匹配
const arrayLike = { 0: 1, 1: 2, length: 2 };
console.log(baseGetTag(arrayLike)); // '[object Object]'
console.log(!!typedArrayTags[baseGetTag(arrayLike)]); // false
// 示例:函数对象的类型标签不匹配
const func = function () {};
console.log(baseGetTag(func)); // '[object Function]'
console.log(!!typedArrayTags[baseGetTag(func)]); // false
// 示例:Date对象的类型标签不匹配
const date = new Date();
console.log(baseGetTag(date)); // '[object Date]'
console.log(!!typedArrayTags[baseGetTag(date)]); // false
这一步通过检查类型标签是否存在于 typedArrayTags 映射中,准确识别出具体的 TypedArray 类型。双重否定(!!)将结果转换为布尔值。
总结
baseIsTypedArray 函数通过三重检查实现了对类型化数组的精确识别:
- 确保值是对象类型
- 验证其具有有效的长度属性
- 匹配特定的内部类型标签
这种多层次的验证确保了类型判断的准确性,能够有效区分 TypedArray 与普通数组和类数组对象。