# hasPath
# Description
hasPath 用于检测 object 上是否存在路径 path 。
# Params
(object, path)
# Return
Boolean
# Depend
import castPath from './.internal/castPath.js'
import isArguments from './isArguments.js'
import isIndex from './.internal/isIndex.js'
import isLength from './isLength.js'
import toKey from './.internal/toKey.js'
castPath 源码分析
isArguments 源码分析
isIndex 源码分析
isLength 源码分析
toKey 源码分析
# Code
const hasOwnProperty = Object.prototype.hasOwnProperty
function hasPath(object, path) {
path = castPath(path, object)
let index = -1
let { length } = path
let result = false
let key
while (++index < length) {
key = toKey(path[index])
if (!(result = object != null && hasOwnProperty.call(object, key))) {
break
}
object = object[key]
}
if (result || ++index != length) {
return result
}
length = object == null ? 0 : object.length
return !!length && isLength(length) && isIndex(key, length) &&
(Array.isArray(object) || isArguments(object))
}
# Analyze
首先通过
castPath
将path
转为 路径数组while
循环遍历,使用toKey
将path[index]
转为合法的属性key
,每次都会判断object
不为null
或者undefined
,并且在其原型上存在key
,将判断的结果赋值给result
如果
result
为false
, 则跳出循环,否则将object[key]
赋值给object
,更新到下一层如果
result
为true
或者++index != length
,也就是说 如果result
为true
则表示遍历完了,直接返回结果即可也有可能遍历完了
result
不为true
的,那就判断 当前遍历完成的下标+1 是不是等于length
,如果不等于,就说明while
循环没有走完,在中途就退出了,那就说明path
不在object
中, 当然也是直接返回result
最终也有可能出现
result
为false
,并且++index == length
的情况hasPath(new Array(5), 4)
此时
result
的结果就是false
,但是++index == length
,对于稀疏数组的判断Object.prototype.hasOwnProperty.call
返回的是false
所以最后这里 对于稀疏数组和
arguments
做了处理。也就是如果while
循环到最后的object
存在length
,length
有值 ,并且length
是合法的, 最后的key
是 合法的索引,然后 最后的object
是 数组或者arguments
对象 的话,那么也认为是path
路径是合法的const temp = { a: { b: { c: new Array(5) } } } console.log('temp', hasPath(temp, 'a.b.c.4')) // true
# Remark
- Object.prototype.hasOwnProperty() MDN (opens new window) 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
# Example
const a = {
a: {
b: 1
}
}
const temp = {
a: {
b: {
c: new Array(5)
}
}
}
const arr = new Array(5)
console.log(hasPath(arr, 4)) // true
console.log(hasPath(a, ['a', 'b'])) // true
console.log(hasPath(temp, 'a.b.c.4')) // true