给对象赋值时到底发生了什么?

前言

myobject.info = "bat"我们都知道这是在干嘛,没错,是在给对象myobject赋值!!!但你考虑过此时都发生了神马?

创建对象的方法

1、文字形式

var myobject = {}

2、构造函数 

var myobject = new Objet()

揭秘

myobject.info = "bat",在给对象赋值时,首先会在myobject中查找是否存在属性info,情况可以分为以下三种

1、myobject中存在info属性,那么“只会”修改myobject中的该属性值,为啥说只会,详情见情况3

2、myobject中不存在该属性,那么会在[[Prototype]]链上层查找该属性,此时又分为两种情况

  •  [[Prototype]]链上层不存在info属性,那么就会在myobject上创建该属性并赋值bat
  •  [[Prototype]]链上层存在该属性,情况较为复杂等下说

3、myobject中存在info属性,[[Prototype]]链上层也存在该属性,那么这个info属性就是“屏蔽”属性,也就是说实例属性会屏蔽原型链上的同名属性,我们在使用myobject.info = "bat"时只会更

改实例上的同名属性的值,而无法更改原型链上的同名属性的值!!!

向[[Prototype]]链上层已经存在的属性赋值就一定会触发屏蔽吗?

接下来说一下上面说的较为复杂的情况

此时的情况是myobject中不存在属性info,[[Prototype]]链上层存在属性info

1、[[Prototype]]链上层存在属性info,这个属性不是只读的,也就是writable:true,那么会在myobject上直接创建该属性并赋值

2、[[Prototype]]链上层存在属性info,这个属性是只读的,也就是writable:false,此时运行在严格模式下会抛出error,非严格模式下(标准模式)会静默失败

3、[[Prototype]]链上层存在属性info,这个属性是setter,也就是访问描述符,那么会调用setter,foo属性并不会被添加到myobejct中,也不会重新定义foo这个setter,因为setter会屏蔽[[PUT]]

由此可见向[[Prototype]]链上层已经存在的属性赋值不一定会触发屏蔽

特例

如果我们希望第二种和第三种情况也发生屏蔽,那么就不要使用“=”,而是使用Object.defineProperty()来向myobject添加属性!!!

在这里对于原因不做详细的解释了,只要知道“只读属性会阻止[[Prototype]]链下层隐式创建同名属性这个限制”只存在于“=”赋值中,使用Object.defineProperty()则不受影响就好

其实这样做主要是为了模拟类属性继承,我们将[[Prototype]]链上层的info属性看作父类中属性,它会被myobejct继承,这样一来[[Prototype]]链上层的info属性是只读的那么自然myobejct中的info

属性也是只读的不可以创建,但是一定要注意实际上并不会发生类似的继承复制

原文地址:https://www.cnblogs.com/kunmomo/p/10492325.html