奇怪的面试题
最近碰到一道奇奇怪怪的面试题,对象使用数组的push方法后会发生什么?题目如下:
var obj = {
'2':3,
'3':4,
'length':2,
'splice':Array.prototype.splice,
'push':Array.prototype.push
}
obj.push(1)
obj.push(2)
obj.push(3)
console.log(obj);
求最后打印出的的obj是什么?
答案是:
{
'2':1
'3':2,
'4':3,
'length':5,
'splice':Array.prototype.splice,
'push':Array.prototype.push
}
原因是:
obj是有长度的,相当于类数组,调用数组的push方法,会在数组的最后添加一项。
-
第一次调用,相当于数组下标为2的那一项被赋值为1,下标为2,当做作为对象的key值的时候,会隐式调用toString方法转换为字符串2。这样则与obj本来的key"2"重复了,原来的key为2的value就会被覆盖掉。以此类推
-
第二次push的时候,数组下标为3的那一项被赋值为2.下标为3,隐式转换为字符串之后把之前的key覆盖掉
"3":4 =>"3":2
-
第三次push的时候,数组下标为4的那一项被赋值为3,下标为4 隐式转换为字符串后没有之前的key与它冲突,所以向原对象中添加
"4":3
至于长度为什么会变,这就涉及数组push方法的原理了
push方法大概是这样实现的
function my_push(x){
this.length===undefined?this.length=0:this.length
//自己的长度为索引赋值
this[this.length] = x
//此处还需注意length会自动加一
this.length++
return this.length;
}
现在我们来测试一下:
var obj = {
'2':3,
'3':4,
'length':2,
'splice':Array.prototype.splice,
'push':Array.prototype.push
}
my_push.call(obj,1)
my_push.call(obj,2)
my_push.call(obj,3)
console.log(obj)
结果是和上面一样的。
至于为什么要在my_push函数中添加这样的一句话
this.length===undefined?this.length=0:this.length
看下面的代码就知道了
let obj2 = {
'2':3,
'3':4,
'len':2,
'push':Array.prototype.push
}
obj2.push(1) //obj[0] = 1
obj2.push(2) //obj[1] = 2
obj2.push(5) //obj[2] = 5
console.log(obj2);
注意啊,这里是没有长度length的,结果输出为
'0': 1,
'1': 2,
'2': 5,
'3': 4,
'len': 2,
'push':Array.prototype.push
length: 3
可以看到运行了执行push操作,自动为obj2添加了一个length的属性,并将属性值设置为了0,也就是说当length为undefined的时候,会自动添加一个length属性并初始化为0
。
这就是为什么要在my_push里添加这样一句话this.length===undefined?this.length=0:this.length
了
下面我们接着来测试一下
let obj2 = {
'2':3,
'3':4,
'len':2,
'push':Array.prototype.push
}
my_push.call(obj2,1)
my_push.call(obj2,2)
my_push.call(obj2,5)
console.log(obj2)
输出为:
'0': 1,
'1': 2,
'2': 5,
'3': 4,
'len': 2,
'push':Array.prototype.push
length: 3
和前面的直接调用obj.push的输出结果是一样的。
后话
感觉面试都爱出一些奇奇怪怪的题,就是那种在真实开发不会用到的题,太卷了,太卷了,心累!!!