Lodash 源码阅读 - isFunction
功能概述
isFunction 函数用于检查一个值是否为函数类型。它能够准确识别各种函数形式,包括普通函数、生成器函数、异步函数和代理函数等。
前置学习
在深入理解 isFunction 之前,建议先了解以下相关函数:
- isObject:检查值是否为对象类型,是 isFunction 的第一层过滤
- baseGetTag:获取值的内部 [[Class]] 标签,用于区分不同类型的函数
此外,对以下 JavaScript 概念的理解也会有所帮助:
- 函数类型的多样性:JavaScript 中的各种函数类型(普通函数、箭头函数、生成器函数、异步函数等)
- Object.prototype.toString:理解这个方法如何识别对象的内部类型
- Safari 浏览器的类型判断问题:为什么 isFunction 不直接使用 typeof 操作符
isFunction 是 Lodash 中重要的类型判断函数,用于确保操作的对象确实是函数,避免在调用非函数值时发生运行时错误。
源码实现
function isFunction(value) {
// 排除非对象类型的值
if (!isObject(value)) {
return false;
}
// The use of `Object#toString` avoids issues with the `typeof` operator
// in Safari 9 which returns 'object' for typed arrays and other constructors.
var tag = baseGetTag(value);
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}
实现原理解析
1. 排除非对象类型的值
if (!isObject(value)) {
return false;
}
JavaScript 中函数本质是对象,排除非对象类型的值,确保仅对象类型的值进入后续类型判断。
2. 内部标签检查
var tag = baseGetTag(value);
使用 baseGetTag 函数(相对准确)获取值的内部 [[Class]] 标签,例如:
baseGetTag(function () {}); // "[object Function]"
baseGetTag(function* () {}); // "[object GeneratorFunction]"
baseGetTag(async function () {}); // "[object AsyncFunction]"
baseGetTag(new Proxy({}, {})); // "[object Proxy]"
3. 函数类型匹配
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
通过检查标签值来匹配不同类型的函数:
- funcTag:普通函数标签 '[object Function]'
- genTag:生成器函数标签 '[object GeneratorFunction]'
- asyncTag:异步函数标签 '[object AsyncFunction]'
- proxyTag:代理函数标签 '[object Proxy]'
4. 使用示例
// 普通函数
function foo() {}
isFunction(foo); // => true
// 箭头函数
const arrow = () => {};
isFunction(arrow); // => true
// 异步函数
async function asyncFoo() {}
isFunction(asyncFoo); // => true
// 生成器函数
function* generator() {}
isFunction(generator); // => true
// 类
class MyClass {}
isFunction(MyClass); // => true
// 非函数类型
isFunction(42); // => false
isFunction("function"); // => false
isFunction({}); // => false
isFunction([]); // => false
isFunction(null); // => false
总结
该函数通过 类型过滤 + 标签校验 的组合策略,精准识别 JavaScript 中的函数类型,同时规避了 typeof 在旧版浏览器中的兼容性问题