Lodash 源码阅读-hasIn
概述
hasIn
是 Lodash 中的一个函数,用于检查对象中是否存在指定的属性路径,它不仅检查对象自身的属性,还会检查从原型链继承的属性。这个函数特别适合处理继承关系和需要考虑原型链的场景。
前置学习
依赖函数
- hasPath:内部函数,是路径检查的核心实现,负责解析路径并逐级遍历检查
- baseHasIn :内部函数,使用
in
操作符检查属性(包括继承属性) - castPath:将不同格式的路径转换为标准数组格式
- toKey:将路径片段转换为有效的对象属性键
技术知识
- JavaScript 原型链:JavaScript 中对象通过原型链继承属性和方法的机制
- in 操作符:用于检查属性是否存在于对象或其原型链中
- 属性路径 :表示嵌套对象属性的方式,如
a.b.c
或['a', 'b', 'c']
源码实现
javascript
/**
* Checks if `path` is a direct or inherited property of `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path to check.
* @returns {boolean} Returns `true` if `path` exists, else `false`.
* @example
*
* var object = _.create({ 'a': _.create({ 'b': 2 }) });
*
* _.hasIn(object, 'a');
* // => true
*
* _.hasIn(object, 'a.b');
* // => true
*
* _.hasIn(object, ['a', 'b']);
* // => true
*
* _.hasIn(object, 'b');
* // => false
*/
function hasIn(object, path) {
return object != null && hasPath(object, path, baseHasIn);
}
实现思路
hasIn
函数的实现非常简洁,主要由以下几个关键步骤组成:
- 空值检查 :确保输入对象不是
null
或undefined
- 委托路径检查 :将实际的路径检查工作委托给
hasPath
函数 - 使用 baseHasIn :通过传入
baseHasIn
函数作为检查方法,实现对继承属性的支持
这种设计让 hasIn
能够处理各种格式的路径输入,同时正确处理继承属性。
源码解析
函数解析
javascript
function hasIn(object, path) {
return object != null && hasPath(object, path, baseHasIn);
}
这个简短的实现包含两个关键部分:
-
object != null
:检查对象是否存在(不是null
和不是undefined
)。如果对象不存在,立即返回false
,避免后续操作出错。 -
hasPath(object, path, baseHasIn)
:如果对象存在,调用hasPath
函数进行路径检查:object
:要检查的对象path
:属性路径,可以是字符串(如'a.b.c'
)或数组(如['a', 'b', 'c']
)baseHasIn
:用于检查单个属性的函数
baseHasIn 函数实现
javascript
function baseHasIn(object, key) {
return object != null && key in Object(object);
}
baseHasIn
函数使用 in
操作符检查属性是否存在,这与 baseHas
(使用 hasOwnProperty
)不同,in
操作符会检查对象自身和原型链上的属性。
has 与 hasIn 的比较
为了更好地理解 hasIn
,我们可以与 has
函数进行比较:
javascript
// has 实现
function has(object, path) {
return object != null && hasPath(object, path, baseHas);
}
// hasIn 实现
function hasIn(object, path) {
return object != null && hasPath(object, path, baseHasIn);
}
主要区别在于:
has
使用baseHas
,通过hasOwnProperty
只检查对象自身的属性hasIn
使用baseHasIn
,通过in
操作符检查对象自身和原型链上的属性
总结
hasIn
是一个简洁而强大的函数,通过利用 JavaScript 的原型继承机制,它提供了一种检查对象属性(包括继承属性)的可靠方式。与只检查对象自身属性的 has
相比,hasIn
更适合处理继承场景、接口检测和框架开发。
其核心实现依赖于 hasPath
函数的路径遍历能力,以及 baseHasIn
函数通过 in
操作符检查属性的能力。这种组合让 hasIn
能够处理各种复杂的属性路径,同时正确识别继承的属性。
在实际应用中,hasIn
特别适合以下场景:
- 需要考虑继承属性的属性检查
- 检查对象是否实现了特定接口
- 处理原型链上的深层嵌套属性
- 安全地访问可能是继承的方法和属性