数组
类数组
类数组,ArrayLike。
Reference: https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/76open in new window
var obj = {
'2': 3,
'3': 4,
'length': 2,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
// 结果
// Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]
// 2: 1
// 3: 2
// length: 4
// push: ƒ push()
// splice: ƒ splice()
// __proto__: Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
涉及知识点:
类数组(ArrayLike
):一组数据,由数组来存,但是如果要对这组数据进行扩展,会影响到数组原型,ArrayLike
的出现则提供了一个中间数据桥梁,ArrayLike
有数组的特性, 但是对ArrayLike
的扩展并不会影响到原生的数组。
push
方法:push
方法有意具有通用性。该方法和call()
或apply()
一起使用时,可应用在类似数组的对象上。push
方法根据length
属性来决定从哪里开始插入给定的值。如果length
不能被转成一个数值,则插入的元素索引为0
,包括length
不存在时。当length
不存在时,将会创建它。
唯一的原生类数组对象是String
,尽管如此,它们并不适用该方法,因为字符串是不可改变的。
对象转数组的方式:
Array.from()
、splice()
、concat()
等
上题分析:
这个obj
中定义了两个key
值,分别为splice
和push
分别对应数组原型中的splice
和push
方法,因此这个obj
可以调用数组中的push
和splice
方法,调用对象的push
方法:push(1)
,因为此时obj
中定义length
为2
,所以从数组中的第二项开始插入,也就是数组的第三项(下表为2
的那一项),因为数组是从第0
项开始的,这时已经定义了下标为2
和3
这两项,所以它会替换第三项也就是下标为2
的值,第一次执行push
完,此时key
为2
的属性值为1
,同理:第二次执行push
方法,key
为3
的属性值为2
。
因为只是定义了2和3两项,没有定义0和1这两项,所以前面会是empty。 如果将这道题改为:
var obj = {
'2': 3,
'3': 4,
'length': 0,
'splice': Array.prototype.splice,
'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
2
3
4
5
6
7
8
9
10
此时的打印结果就是:
Object(2) [1, 2, 2: 3, 3: 4, splice: ƒ, push: ƒ]
0: 1
1: 2
2: 3
3: 4
length: 2
push: ƒ push()
splice: ƒ splice()
__proto__: Object
2
3
4
5
6
7
8
9
原理:此时length
长度设置为0
,push
方法从第0
项开始插入,所以填充了第0
项的empty
。至于为什么对象添加了splice
属性后并没有调用就会变成类数组对象这个问题,这是控制台中 DevTools 猜测类数组的一个方式:https://github.com/ChromeDevTools/devtools-frontend/blob/master/front_end/event_listeners/EventListenersUtils.js#L330open in new window