JS对象的数据属性,访问器属性,防篡改对象

JS对象的数据属性,访问器属性,防篡改对象

1. 数据属性

高程是这样定义数据属性的:数据属性包含一个数据值的位置。在这个位置可以读取和写入值,数据属性有四个描述其行为的特性。(第三版6.1.1节,P139)

这里引用高程上的详细解释(第三版6.1.1节,P139)

[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。对于直接在对象上定义的属性,它们的这个特性默认为true

[[Enumerable]]:表示能否通过for-in循环返回属性。对于直接在对象上定义的属性,这个特性默认值为true

[[Writable]]:表示能否修改属性的值。对于直接在对象上定义的属性,他们的这个特性默认为true

[[Value]]:包含这个属性的数据值。读取属性值的时候,从这个位置读,写入属性值的时候,新值保存在这个位置。这个特性默认为undefined

当修改configurable属性为false的时候,则该属性被认为是不可配置的,并且没有属性可以被改变(除了单项修改writable为false);

Q1:现在存在一个问题,如果修改configurable属性为false,那么根据解释,只能单向修改writable为false,那么如果writable为true,能否改变属性的值?

根据高程上的描述,值也算一个特性,理论上值不能被修改,但是实际上值是可以被修改的,大家看下面的例子:

var a = {b:'aa',c:'dd'};
a.b = 'cc';

Object.defineProperty(a,'b',{
    configurable:false
});

Object.defineProperty(a,'b',{
    value:'dd'
});
console.log(a); //{ b: 'dd', c: 'dd' }

a.b = 'ee';
console.log(a); //{ b: 'ee', c: 'dd' }

但是如果将wirtable修改为false就不能被修改值了,如下例子(接着上边)

Object.defineProperty(a,'b',{
    writable:false
});
a.b = 'ff';

console.log(a); //{ b: 'ee', c: 'dd' }

所以可以这么理解,configurable属性是控制configurable属性本身、enumerable和writable这三个特性的。 而writable是控制value这个特性的,将configurable设置为false并不影响value的可改变性,value是否可改变只与writable有关。

2. 访问器属性

四个:

[[configurable]]
[[Enumberable]]
[[get]]
[[set]]

高程上的解释和详细定义就不赘述了。

有一点需要解释一下,根据高程的上的一个例子,我做了一个类似的例子

var book = {
    _year:2004,
    edition:1
};

Object.defineProperty(book,'year',{
    get:function () {
        return this._year;
    },
    set:function (v) {
        this._year = v+1;
    }
});

console.log(book._year); //可以直接访问以_year开头的属性,事实上这个和普通属性没什么区别!
console.log(book.year);
book.year = 2332;
console.log(book.year);

高程上解释:以_开头的属性是访问器属性,事实上没有语法的规定,但这是约定俗成的;虽然可以直接访问以_开头的属性,但是作为这个模块的使用者,应该只是访问同名的不带_的属性;作为这个模块的编写者,应该编写一个同名的不带_的属性作为访问器。比如year就是_year属性的访问器。

Q2:还有一个问题,如果在设置属性的时候同时指定访问器属性和数据属性会发生什么?

测试了一下,会报错:

Object.defineProperty(book,'year',{
    get:function () {
        return this._year;
    },
    set:function (v) {
        this._year = v+1;
    },
    value:'22'
}); //TypeError: Invalid property descriptor. Cannot both specify accessors(构造器) and a value or writable attribute, #<Object>

最后,一旦将configurable指定为false,4个访问器属性都无法再修改了。

2.1 读取属性的特性

利用Object.getOwnPropertyDescriptor(object,object.name)来返回一个为object.name量身定做的描述符对象。含有该属性的特性信息。

3. 防篡改对象

有三种不同程度的防篡改级别

  1. 不可扩展:Object.preventExtensions(object)
  2. 密封:Object.seal(object)
  3. 冻结:Object.freeze(object)

用一张表可以解释防篡改的程度

            添加新的属性/方法   configurable    writable
不可扩展           ×                  √             √
密封              ×                  ×             √
冻结              ×                  ×             ×

检测是否不可扩展:Object.isExtensiable(object) 检测是否密封: Object.isSealed(object) 检测是否冻结: Object.isFrozen(object)

转载于:https://my.oschina.net/u/3400107/blog/1844524

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值