# arrayLikeKeys
# Description
创建一个数组,将 value 对应的 key 放到数组中,并返回,如果是 Array,arguments, buffer,typedArray ,会收集索引
# Params
(value, inherited)
inherited 是否收集原型链上的属性
# Return
Array
# Depend
import isArguments from '../isArguments.js'
import isBuffer from '../isBuffer.js'
import isIndex from './isIndex.js'
import isTypedArray from '../isTypedArray.js'
isArguments 源码分析
isBuffer 源码分析
isIndex 源码分析
isTypedArray 源码分析
# Code
const hasOwnProperty = Object.prototype.hasOwnProperty
function arrayLikeKeys(value, inherited) {
const isArr = Array.isArray(value)
const isArg = !isArr && isArguments(value)
const isBuff = !isArr && !isArg && isBuffer(value)
const isType = !isArr && !isArg && !isBuff && isTypedArray(value)
const skipIndexes = isArr || isArg || isBuff || isType
const length = value.length
const result = new Array(skipIndexes ? length : 0)
let index = skipIndexes ? -1 : length
while (++index < length) {
result[index] = `${index}`
}
for (const key in value) {
if ((inherited || hasOwnProperty.call(value, key)) &&
!(skipIndexes && (
// Safari 9 has enumerable `arguments.length` in strict mode.
(key === 'length' ||
// Skip index properties.
isIndex(key, length))
))) {
result.push(key)
}
}
return result
}
# Analyze
- 首先 判断
array
,arguments
,buffer
,typedArray
这几种类型,创立标识符skipIndexes
- 如果
skipIndexes
标识符为真,则result
数组的长度就为value.length
,否则长度为0
- 对于
index
的处理也是如此,如果skipIndexes
标识符为真,则为-1
, 否则等同于length
- 使用
while
循环遍历,这里如果index == length
,因为是++index
, 所以不会进入while
循环,否则就给数组每一项设置为字符串类型index
,使用while
是为了遍历 稀疏数组 - 使用 for in 来遍历 value 自身和原型链上的属性
- (inherited || hasOwnProperty.call(value, key))
- 本来只遍历
value
存在的属性(hasOwnProperty.call(value, key)
),但是因为有标识符inherited
的关系,如果传入了true
对于原型链上的可枚举属性也会遍历
- 本来只遍历
- !(skipIndexes && ((key === 'length' || isIndex(key, length))))
- 类数组的下标,在之前已经进行过处理,所以这里对于 index 不做处理
skipIndexes && isIndex(key, length)
- 因为 在 Safari 9 的严格模式下,
arguments
的length
属性变成了可枚举,所以这里排除了length
属性的收集
- 类数组的下标,在之前已经进行过处理,所以这里对于 index 不做处理
- (inherited || hasOwnProperty.call(value, key))
# Remark
- for...in MDN (opens new window) 语句以任意顺序遍历一个对象的除 Symbol 以外的可枚举属性
- hasOwnProperty() MDN (opens new window) 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
# Example
const a = {
0: 'A',
1: 'B',
2: 'C',
3: 'D',
length: 4
}
const b = [1,2,3,3,4,5,6,7]
const c = new Uint8Array(10)
function Test(){}
Test.prototype.name = 'Test'
Test.prototype.type = 'Function'
const d = new Test
d['a'] = 1
d['b'] = 2
d['c'] = 3
d['d'] = 4
console.log(arrayLikeKeys(a)) // [ '0', '1', '2', '3', 'length' ]
console.log(arrayLikeKeys(b)) // ['0', '1', '2', '3', '4', '5', '6', '7' ]
console.log(arrayLikeKeys(c)) // ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]
console.log(arrayLikeKeys(d)) // [ 'a', 'b', 'c', 'd' ]
console.log(arrayLikeKeys(d, true)) // [ 'a', 'b', 'c', 'd', 'name', 'type' ]