# iskey
# Description
isKey
的作用是用来判断传入的 value
是否为合法的属性名, 检查 value
是否是属性名称而不是属性路径(如传入 a.b.c
或者 a[0].b.c
可能会返回 false。)。
# Params
(value, object)
value: 需要校验的值 object: 所属对象
# Return
Boolean
# Depend
import isSymbol from '../isSymbol.js'
# Code
const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/
const reIsPlainProp = /^\w*$/
function isKey(value, object) {
if (Array.isArray(value)) {
return false
}
const type = typeof value
if (type === 'number' || type === 'boolean' || value == null || isSymbol(value)) {
return true
}
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
(object != null && value in Object(object))
}
# Analyze
#
reIsDeepProp
, 用于匹配属性路径中的属性名称。/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/
图解如下
在 lodash
中,像 a.b.c
和 a[0].b.c
这种可能会被当作属性路径对待,像 get
这些的函数支持传入这样的路径来获取嵌套对象的值,在这个正则中,主要就是匹配 .
[]
这种属性值,同时支持转义字符,如 [\'b\']
reIsPlainProp
, 用于匹配[0-9A-Za-z_]
/^\w*$/
, 图解如下
# 源码分析
- 首先判断
value
如果是Array
,直接return false
- 其次判断
value
的类型是否为Number
、Boolean
、Null
,Symbol
,除Symbol
外,在做Object
的Key
值时,都会默认转换为String
,而在ES6
中,Symbol
本身就可以做Object
的Key
值 (Symbol术语 MDN (opens new window)) - 开始处理字符串类型, 如果是
\w
类型则直接返回true
,接着判断如果 不是.
[]
(如:a.b.c
a['b'].c
) 这种类型的情况下,返回true
- 特殊情况处理,如果非要 传入
a.b.c
这种形式的情况,就需要用到 第二个参数object
来判断,如果传入的对象不为空,并且value
是object
的Key
则返回true
# Remark
- in运算符 MDN (opens new window)
- Object 属性名称 MDN (opens new window)
- 判断字符串时,先判断
\w
后判断其他的(其实只判断第二个正则也可以,还是因为性能原因),是因为第二个正则太复杂,为性能考虑,首先先判断\w
# Example
isKey(3) // true
isKey('a') // true
isKey('a.b.c') // false
isKey('a.b.c', {"a.b.c": 1}) // true