bibi7 / fe-daily-increase

一个记录开发日常和奇奇怪怪的点的repo
MIT License
5 stars 0 forks source link

object的push妙用 #30

Open bibi7 opened 5 years ago

bibi7 commented 5 years ago
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: ƒ]

有几个值得注意的地方,首先push,来瞅瞅MDN上push的定义:

push方法将值追加到数组中。

push 方法有意具有通用性。该方法和 call()apply() 一起使用时,可应用在类似数组的对象上。push 方法根据 length 属性来决定从哪里开始插入给定的值。如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。

唯一的原生类数组(array-like)对象是 Strings,尽管如此,它们并不适用该方法,因为字符串是不可改变的。

也就是说,一个正常的push会发生如下过程:

const array = [1, 2, 3]
array.push(4)
  1. 首先会去获取array.length,得到的结果为3
  2. 在array下标是3的地方,插入数据,array[3] = 4

回到上文:

obj.push(1)
obj.push(2)
  1. 首先push(1),会先获取obj.length,得到2,则obj[2] = 1,同时返回更新过的length属性
  2. 同上,获取最新的length属性,则obj[3] = 2

由于对象在进行复制的时候,健名不会区分字符串于数字,测试:

var object = {'1':'z1'}
object[1] = 'z2'
console.log(object) //{1: "z2"}

所以两次的push赋值分别会覆盖对象原本的两个属性。

另一个点:伪数组 当使用console.log输出的时候,因为obj具有 length 属性和 splice 方法,故将其作为伪数组打印出来,由于下标0和1暂无值,所以为两个empty。最终打印出:

Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]