JS_属性的设置过程

181 阅读2分钟

属性的设置过程

myObject.foo = "bar";

就这么一句简单的赋值过程,会经历什么呢?

来自《你不知道的Javascript》上第五章;

第一种情况:

myObject对象中包含foo属性,那么这种最简单,只会对foo属性的值进行修改;

第二种情况:

foo属性并不直接存在于myObject对象中,这时候就会对原型链[[Prototype]]进行遍历,类似[[get]]操作;如果原型链上找不到foo属性,那么就会在myObject对象上直接添加foo属性;

第三种情况:

foo属性不仅在myObject对象中,还存在于原型链上层;这时候会发生屏蔽;myObject.foo会优先选择原型链最底层的foo属性;

WOW,我的天,原来屏蔽有这么多道道;

第四种情况:

foo属性并不直接存在于myObject对象中,而是存在于原型链的上层

  1. 如果foo属性存在于原型链的上层,且该属性不是只读属性(writable:false),这时候就会将foo属性添加到myObject对象中,foo属性就是第三种情况的屏蔽属性

    let topobj = {foo: 'topFoo'}
    let myobj = Object.create(topobj)
    console.log(myobj)
    myobj.foo = 'myFoo'
    

    image.png

  2. 但是foo属性存在于原型链的上层,但是它是只读的属性,那么无法修改已有属性或者在myobj对象上创建屏蔽属性;

    let topObj = {}
    Object.defineProperty(topObj, "foo", {
       value: 'topFoo',
       writable: false
    })
    let myObj = Object.create(topObj)
    console.log("myObj before:", myObj)
    myObj.foo = 'myFoo'
    console.log("myObj after:", myObj)
    

    从输出结果可以看到赋值被忽略了:

    image.png 严格模式下,当对foo属性赋值时,直接报错:

image.png

  1. 如果在 [[Prototype]] 链上层存在 foo 并且它是一个 setter(参见第 3 章),那就一定会调用这个 setter。foo 不会被添加到(或者说屏蔽于)myObject,也不会重新定义 foo 这个 setter。

对于这种情况,我没有特别理解,下面是我写的代码:和输出结果,不知道是不是我写的有问题🤨;各位友友如果有见解,希望评论里指正;

let topObj = {}
let foovalue = 'topFoo'
Object.defineProperty(topObj, "foo", {
    get() {
        return foovalue;
    },
    set(value) {
        foovalue = value
        console.log('seting', value);
    }
})
let myObj = Object.create(topObj)
console.log("myObj before:", myObj)
myObj.foo = 'myFoo'
console.log("myObj after:", myObj)

输出结果:

image.png