携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
大家好!我是前端爬楼工程师🚹,一个野生程序员。好奇新技术,仰慕牛大佬。如果喜欢我的文章,可以关注➕点赞,为我注入能量,与我一同成长吧~
在我们使用 var o = {} 或者 var o = new Object(),此时o的[[Prototype]]属性对应的是Object
之前我们提过[[Get]]属性,
看这个例子:
var o = {a :1}
o.a // 1
a属性的值,就是通过[[Get]]获取的,如果a不在对象o中,此时就会通过[[Prototype]]找原型对象上是否有属性的值,如果有返回,反之返回undefined
我们知道创建对象方式还有Object.create()
Object.create()
它的原理就是将创建一个对象(返回值),将此对象的
[[Prototype]]关联到传入的那个对象。
var another = {a:1}
var o = Object.create(another)
o.a //1
-
在调用
Object.create(another)时候,o的[[Prototype]]指向another,所以a是从another那里得到的。如果another上找不到并且[[Protoype]]不为空,会继续查找下去。 -
for...in遍历原理查找方式和上面查找属性的方式类似,并且是可枚举的来查找属性 -
而单独的
in操作也查找原形链(属性可以是可枚举,也可以不是)'a' in o
按照[[Prototype]]寻找什么时候是尽头呢?它的顶端是Object.prototype.
所有普通对象
[[Prototype]]指向Object.prototype,这也是为何普通对象也有Object的一些功能,如toString,valueOf,hasOwnProperty(),isPrototypeOf()等.
属性设置和屏蔽,有学问!
o.foo = 'bar'
o上如果有foo属性,这将是个修改操作,- 如果没有
foo属性,[[Prototype]]会遍历到,如果原型链上没有找到,就会出现以下几种情况:
o的[[Protoype]]上有
foo属性,需要分三种情况来分析o.foo = 'bar'
- 如果
o的[[Prototype]]上有foo属性且writable不为false,则会为o上创建一个屏蔽属性foo; - 如果
o的[[Prototype]]上有foo属性且标记为只读(writable:false),那么赋值代码无效,如果在严格模式会抛异常; - 如果
o的[[Prottype]]上存在foo并且有setter,那一定会调用这个setter,foo不会添加到o上;
隐式屏蔽
var another = {a:1}
var o = Object.create(another)
o.a ++ // 2
another.a // 1
这里的
o上没有a,根据[[Prototype]]原型链上找得到1,o.a++ => o.a = o.a+1 => o.a = 1 + 1,触发了[[Put]],在o上添加的屏蔽属性a