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);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
考察
本题考查类数组、push
方法以及length
属性的应用
# 解析
- 首先定义了一个对象并将地址传递给了变量 obj
观察对象,拥有 length
属性并且是其值为正整数,以及 splice
属性,并且其值对应函数(详见本题第二、三部分证明),所以可以被解析成类数组。
- 既然是类数组,对象的键就是数组的下标,对象的值就是数组当前下标的值
此时撇开 length
属性不管,这个类数组可以看作:[empty, empty, 3, 4]
贴士
介绍 push()
方法:它会根据 length
属性来决定从哪里开始插入给定的值,详见 MDN (opens new window)
所以当执行
push(1)
时,length
属性起作用,它将这个类数组的长度截断了,此时可以看作:[empty, empty]
之后进行了两次
push
操作,结果可以看作:[empty, empty, 1, 2]
,
然后类数组length
属性更新为4。
- 打印结果:
[empty × 2, 1, 2, splice: ƒ, push: ƒ]
# 查阅 Chrome DevTools
我去查阅了开发者工具文档,详见ChromeDevTools (opens new window),得到如下结论:
判断 arrayLike
的机制
- 存在且是对象
- 对象上的 splice 属性是函数类型
- 对象上有 length 属性且为正整数
function isArrayLike(obj) {
if (!obj || typeof obj !== 'object') {
return false;
}
try {
if (typeof obj.splice === 'function') {
const len = obj.length;
return typeof len === 'number' && (len >>> 0 === len && (len > 0 || 1 / len > 0));
}
} catch (e) {
}
return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 一次手段不聪明的证明
用不聪明的办法验证一个对象的 length
属性为 正整数 ,同时 splice
属性为函数时,对象的函数输出结果就会变成类数组。
//1. length对应数字,splice对应函数(这里只用了空函数)
var obj1 = {
length: 1,
splice: function () { },
};
// 打印结果:Object [empty, splice: ƒ] ===> 类数组
//2. length对应字符串,splice对应函数
var obj2 = {
length: '1',
splice: function () { },
};
// 打印结果:{length: "1", splice: ƒ} ===> 对象
//3. length对应数字,splice对应空对象
var obj3 = {
length: 1,
splice: {},
};
// 打印结果:{length: 1, splice: {…}} ===> 对象
//4. length对应数字,但是为负数;splice对应函数
var obj4 = {
length: -1,
splice: function () { },
};
//打印结果:{length: "-1", splice: ƒ} ===> 对象
console.log(obj1, obj2, obj3, obj4);
//综上:结论成立
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30