木灵鱼儿
阅读:214
屏蔽属性
前言
对于js的原型链继承,大部分都是知道的,但是对于以下内容,很多人可能并不清楚或者理解不完整,那就是屏蔽属性。
什么是屏蔽属性,其实这个功能来源于面向对象语言中的多态,表示父级定义的属性,在子级可以自己扩展,虽然属性名相同,但是功能却可以不同。
由于js的继承,它不像强类型语言是完全的复制,js对于继承是通过原型链的方式,当子级没有的情况下会通过在原型链上查找。
那么子级如果需要覆写某一个属性,显然它是绝对不能直接修改原型链上的内容,这回导致所有继承的子类产生问题,这显然是不合适的。
于是就有了屏蔽属性,当子级去覆写一个原型上存在的属性时,其实并不会去修改原型链的属性,而是给子级自己添加一个对应的属性,加上就近原则,调用的时候会优先获取到子级自身的这个属性,于是原型上的仿佛就被屏蔽了一样。
但是并不是所有的情况都会在子级自身添加对应的属性。
这就是本文需要讲述的内容。
屏蔽属性的规则
- 如果在 [[Prototype]] 链上层存在名为 foo 的普通数据访问属性并且没有被标记为只读(writable:false),那就会直接在 myObject 中添加一个名为 foo 的新属性,它是屏蔽属性。
- 如果在 [[Prototype]] 链上层存在 foo,但是它被标记为只读(writable:false),那么无法修改已有属性或者在 myObject 上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。否则,这条赋值语句会被忽略。总之,不会发生屏蔽。
- 如果在 [[Prototype]] 链上层存在 foo 并且它是一个 setter,那就一定会调用这个 setter。foo 不会被添加到(或者说屏蔽于)myObject,也不会重新定义 foo 这个 setter。
基于以上原则,此时我们就能很清晰地知道,赋值其实还是有点说法的。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
JavaScript里面继承是怎样实现的?如何避免原型链上的对象被共享?
JavaScript里面继承是怎样实现的?最简单的就是通过原型链继承,然后衍生出几种方法:构造函数继承、组合继承、原型式继承、寄生继承、寄生组合式继承。function Box() { this.name = "鱼儿", this.age = 666 } Box.prototype.run = function(){ return this.name; } function Pox() { this.run = function() { alert(this.name + this.age); } } Pox.prototype = ne...
对象与原型的继承组合模式中仿冒和继承不会冲突吗?
代码部分:function Box(name) { this.name = name; this.famil = ['爷爷','奶奶','爸爸','妈妈']; }; Box.prototype.run = function() { return this.name + this.famil; }; function Desk(name) { Box.call(this,name); }; Desk.prototype = new Box(); 通过对象仿冒,将Box的属性仿冒到Desk中,这样就可以传入参数,也可以算是继承了,但是后面我们又通过Des...
关于面向对象判断是否原型属性的疑问
首先我们需要创建一个构建函数,并为它添加一个实例属性(实例就是被运行的函数)。function Box() {}; var box1 = new Box(); box1.name = 'mu'; 每个函数都会有一个原型,原型里的数据是共享的,多个变量box1运行同一个函数Box(),这个Box()函数原型中的数据是共有的,并且引用地址相同。加上就近原则,当实例属性中有对应的属性,会优先调用实例属性,如果没有,就会去原型中查找。那么我们要去判断这个属性是实例中的属性还是原型中的属性,有两个判断语法:hasOwnProperty() / inhasOwnProperty()是判断属性是否存在...