博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[译]JavaScript:属性赋值和原型链
阅读量:6414 次
发布时间:2019-06-23

本文共 2063 字,大约阅读时间需要 6 分钟。

原文:


本文要研究一下:一个对象的原型链是如何影响该对象自身的属性赋值操作的.本文更详细的阐述了一下上篇文章“”中提到的一个知识点.

原型链

每个对象都有一个包含了一个或者多个对象的原型链,该对象正是这个原型链的起始对象.原型链上的所有对象的所有属性都可以被该对象访问到.例如:

> var proto = { foo: 1 };> var obj = { __proto__: proto, bar: 2 };> obj.foo1> obj.bar2

我们用到了特殊属性 __proto__ 来创建原型链(该属性还没有被所有浏览器广泛支持).对象obj的原型链包含了三个对象:起始处是obj,紧跟着proto,最后是Object.prototype. Object.prototype是Object构造函数的原型对象,绝大部分原型链中都包含了它(大部分,但不是全部):

> Object.prototype.isPrototypeOf({})true> Object.prototype.isPrototypeOf([])true> Object.prototype.isPrototypeOf(new Date())true

而且它是原型链的截止对象:

> Object.getPrototypeOf(Object.prototype)null

普通对象的很多标准方法都是从Object.prototype上继承下来的,比如toString()hasOwnProperty().

为属性赋值

如果你给一个属性赋值,你通常只能修改原型链上的起始对象(也就是对象自身):如果自身属性已经存在了,则改变这个属性的值,否则,创建这个新的自身属性:

> obj.foo = 3;> obj.foo3> obj.hasOwnProperty("foo")true> proto.foo1

这样设计的目的是:一个原型可以为其所有的实例引入了一个公用的初始值(被继承的属性的值).如果给其中一个实例的同名属性执行赋值操作可以改变原型上的那个公用的属性值的话,那么所有实例的初始值都会被改变.为了防止这种情况发生,同时还允许你修改某单个实例的初始值,属性的赋值操作被设计为:仅允许你改变一个已存在的自身属性的值.如果还没有这个自身属性,则会自动创建,再赋值.

访问器和原型链

一个存在于原型链上的访问器属性可以阻止"在该原型链的起始对象上创建同名的自身属性".假如对象obj继承了一个拥有getter和setter的对象:

var obj = {    __proto__: {        get foo() {            return 1;        },        set foo(x) {            console.log("Setter called: "+x);        }    }};

给对象obj的属性foo赋值的话,会调用到其原型上的setter访问器,而不会给obj创建一个自身属性foo,同理,读取obj的foo属性的话,也会调用到其原型上的getter访问器:

> obj.foo = 2;Setter called: 2> obj.foo1

如果你想禁止该属性的赋值操作的话(也就是只读),可以不提供setter:

var obj = {    __proto__: {        get foo() {            return 1;        }    }};

这样的赋值操作,在非严格模式下会静默失败,在严格模式下,会抛出异常:

> (function () { "use strict"; obj.foo = 2; }());TypeError: Cannot set property foo of obj which has only a getter

原型链上的只读属性

如果原型链上的起始对象继承了一个只读属性,则你无法通过赋值操作改变这个属性的值.例如,下面的代码:

var proto = Object.defineProperty({},    "foo",    {        value: 1,        writable: false    });var obj = { __proto__: proto };

你无法给obj.foo赋值:

> (function () { "use strict"; obj.foo = 2; }());TypeError: obj.foo is read-only

这正好和只有getter的访问器属性的表现相一致.这一次,原型上的属性同样可以作为一个共享的初始值,不同的是,我们要防止单个实例更改自己的初始值.如果你想要给obj创建一个自身属性foo,则你可以使用Object.defineProperty()和Object.defineProperties()来完成.

参考

转载地址:http://gqbra.baihongyu.com/

你可能感兴趣的文章
eclipse快捷键(shift+ctrl+l能出来所有的快捷键)
查看>>
mysql
查看>>
一些比较神奇的思路
查看>>
[网络流24题-13]餐巾计划问题
查看>>
flex自定义preloader预加载进度条
查看>>
topcoder srm 420 div1
查看>>
topcoder srm 545 div1
查看>>
PowerShell收发UDP消息包
查看>>
ios 开发日记 13-剖析网易新闻标签栏视图切换(addChildViewController属性介绍)
查看>>
数组去重的几种方式
查看>>
Pascal's Triangle II
查看>>
2019-2-22集合作业
查看>>
页面导航
查看>>
算法:二叉搜索树的后序遍历序列
查看>>
System.Net.WebException: 请求因 HTTP 状态 503 失败
查看>>
拓展随记
查看>>
服务器远程链接
查看>>
所谓的日常 #6 - 焚金闕董卓行兇 匿玉璽孫堅背約
查看>>
[Winform]DataGridView列自适应宽度
查看>>
进程与线程
查看>>