资讯专栏INFORMATION COLUMN

笔记-你不知道的JS-原型

vincent_xyb / 3235人阅读

摘要:如果存在于原型链上层,赋值语句的行为就会有些不同。中包含的属性会屏蔽原型链上层的所有属性,因为总是会选择原型链中最底层的属性。如果不直接存在于中而是存在于原型链上层时会出现的三种情况。类构造函数原型函数,两个函数通过属性和属性相关联。

1 [[Prototype]]

对于默认的 [[Get]] 操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象的 [[Prototype]] 链

所有普通的 [[Prototype]] 链最终都会指向内置的 Object.prototype。由于所有的“普通”(内置,不是特定主机的扩展)对象都“源于”(或者说把 [[Prototype]] 链的顶端设置为)这个 Object.prototype 对象,如:toString,valueOf,hasOwnProperty,isPrototypeOf

var anotherObject = { a:2};
// 创建一个关联到 anotherObject 的对象
var myObject = Object.create( anotherObject ); 
// myObject = { __proto__: {  a:2, __proto__: Object}};
myObject.a; // 2

属性屏蔽

给一个对象设置属性并不仅仅是添加一个新属性或者修改已有的属性值,如myObject.foo = "bar";

如果 myObject 对象中包含名为 foo 的普通数据访问属性,这条赋值语句只会修改已有的属性值。

如果 foo 存在于原型链上层,赋值语句 myObject.foo = "bar" 的行为就会有些不同。

如果属性名 foo 既出现在 myObject 中也出现在 myObject 的 [[Prototype]] 链上层,那么就会发生屏蔽。myObject 中包含的 foo 属性会屏蔽原型链上层的所有 foo 属性,因为myObject.foo 总是会选择原型链中最底层的 foo 属性。

如果 foo 不直接存在于 myObject 中而是存在于原型链上层时 myObject.foo = "bar" 会出现的三种情况。

如果在[[Prototype]]链上层存在名为foo的普通数据访问属性(参见第3章)并且没有被标记为只读(writable:false),那就会直接在 myObject 中添加一个名为 foo 的新属性,它是屏蔽属性。

如果在[[Prototype]]链上层存在foo,但是它被标记为只读(writable:false),那么无法修改已有属性或者在 myObject 上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。否则,这条赋值语句会被忽略。总之,不会发生屏蔽。

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

大多数开发者都认为如果向 [[Prototype]] 链上层已经存在的属性([[Put]])赋值,就一定会触发屏蔽,但是如你所见,三种情况中只有一种(第一种)是这样的。如果你希望在第二种和第三种情况下也屏蔽 foo,那就不能使用 = 操作符来赋值,而是使用 Object.defineProperty(..)来向 myObject 添加 foo。

2 “类”

构造函数+原型函数,两个函数通过 constructor 属性和 prototype 属性相关联。

类关系

function Foo() {}
let foo = new Foo();

1 foo instanceof Foo

instanceof 操作符的左操作数是一个普通的对象,右操作数是一个函数。instanceof 回答的问题是:在 a 的整条 [[Prototype]] 链中是否有指向 Foo.prototype 的对象

2 Foo.prototype.isPrototypeOf( foo )

isPrototypeOf(..) 回答的问题是:在 foo 的整条 [[Prototype]] 链中是否出现过 Foo.prototype 。我们也可以直接获取一个对象的 [[Prototype]] 链。Object.getPrototypeOf(foo); 如Object.getPrototypeOf( foo ) === Foo.prototype; // true 或者 a.__proto__ === Foo.prototype; // true

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109944.html

相关文章

  • 笔记-你不知道JS-原型

    摘要:如果存在于原型链上层,赋值语句的行为就会有些不同。中包含的属性会屏蔽原型链上层的所有属性,因为总是会选择原型链中最底层的属性。如果不直接存在于中而是存在于原型链上层时会出现的三种情况。类构造函数原型函数,两个函数通过属性和属性相关联。 1 [[Prototype]] 对于默认的 [[Get]] 操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象的 [[Prototype]] ...

    AndroidTraveler 评论0 收藏0
  • 你不知道javascript》笔记_对象&原型

    摘要:上一篇你不知道的笔记写在前面这是年第一篇博客,回顾去年年初列的学习清单,发现仅有部分完成了。当然,这并不影响年是向上的一年在新的城市稳定连续坚持健身三个月早睡早起游戏时间大大缩减,学会生活。 上一篇:《你不知道的javascript》笔记_this 写在前面 这是2019年第一篇博客,回顾去年年初列的学习清单,发现仅有部分完成了。当然,这并不影响2018年是向上的一年:在新的城市稳定、...

    seasonley 评论0 收藏0
  • 你不知道JS上》笔记

    摘要:隐式绑定即绑定到最顶层或最近调用对象上显式绑定即用或手动进行绑定方法实现绑定构造函数不存在其实在中不存在构造函数,我们所说的构造函数其实就是普通的函数,它只是用被构造调用而已。 JS是编译型语言 编译发生在代码执行前几微秒,简单来说就是js在执行前要进行编译,编译过程发生在代码执行前几微妙,甚至更短。 编译的步骤 词法分析以var a = 2 为例,词法分析会将其分成三个有意义的代码...

    VPointer 评论0 收藏0
  • 笔记-你不知道JS-对象

    摘要:内置对象,在中,它们实际上只是一些内置函数。这些内置函数可以当作构造函数,使用调用,产生新对象。在必要时语言会自动把字符串字面量转换成一个对象,也就是说你并不需要显式创建一个对象。属性操作符要求属性名满足标识符的命名规范。 1 如何定义 // 声明形式,大部分情况下使用声明形式 let obj ={ a:2, b:3 }; // 构造形式 let obj= = new Obje...

    senntyou 评论0 收藏0
  • JS笔记

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。异步编程入门的全称是前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。 TypeScript 入门教程 从 JavaScript 程序员的角度总结思考,循序渐进的理解 TypeScript。 网络基础知识之 HTTP 协议 详细介绍 HTT...

    rottengeek 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<