# 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