数据属性与访问器属性

数据属性与访问器属性

主要是用在defineProperty这个方法中

JavaScript中定义了两种不同的属性:数据属性和访问器属性。数据属性一般用于存储数据数值,而访问器属性一般进行get/set操作,不能直接存储数据数值。在ES5中,我们为了描述属性(property)的各种特征,定义了特性(attribute)。在JavaScript中不能直接访问特性,我们把它放在两对方括号中,例如[[Enumerable]]。

  • 数据属性

数据属性主要有四个特性描述其行为:

  1. [[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;
  2. [[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;
  3. [[Writable]]:默认为true。表示能否修改属性的值。
  4. [[Value]]:默认值为undefined。表示包含属性的数据值。读写属性值都从这个位置进行。

对于上面直接在person对象上定义的属性,它们的[[Configurable]]、[[Enumerable]]、[[Writable]]特性都被默认设置为true,而[[Value]]特性被设置为特定值。如果想要修改属性默认的特性,可以使用ES5提供的Object.defineProperty()方法,这个方法接收三个参数:属性所在对象、属性的名字和一个描述符对象。描述符对象只能包含上述四个特性的一个或多个。例子如下:

var person = {
    name: "Scott"
}
Object.defineProperty(person,"name",{
    writable:false;
})
 
console.log(person.name);   //"Scott"
person.name = "Evan";
console.log(person.name);   //"Scott"

将person对象name属性的特性writable设置为false,此属性的值为不可修改的,因此对该属性的复制操作会直接忽略。

var person = {
    name: "Scott"
}
Object.defineProperty(person,"name",{
    configurable:false;
})
 
console.log(person.name);   //"Scott"
delete person.name;
console.log(person.name);   //"Scott"

可以看到,当把name属性的特性值configurable设置为false之后,就表示不能从对象中删除属性。但需要注意的是,当把属性定义为不可配置之后,就不能把它变回可配置的了。此时修改除writable之外的其它特性都会报错,例如:

var person = {
    name: "Scott"
}
Object.defineProperty(person,"name",{
    configurable:false;
})
Object.defineProperty(person,"name",{
    configurable:true;    //此处会抛出错误
})

也就是说,在把configurable特性修改为false之后,再修改其它特性就会有限制存在。

  • 访问器属性

访问器属性不包含数据值。它包含一对getter和setter函数。当读取访问器属性时,会调用getter函数并返回有效值;当写入访问器属性时,会调用setter函数并传入新值,setter函数负责处理数据。该属性有四个特性:

  1. [[Configurable]]:默认为true。表示能否通过delete删除属性从而重新定义属性,能否修改属性特性,或者能否把属性修改为访问器属性;
  2. [[Enumerable]]:默认为true。表示能否通过for-in循环返回属性;
  3. [[Get]]:读取属性时调用的函数,默认为undefined;(读取的时候就会触发的函数)
  4. [[Set]]:写入属性时调用的函数,默认为undefined。(改动属性时,就会触发这个函数)

访问器属性不能直接定义,必须通过Object.defineProperty()函数定义,例如:

var person = {
    _name: "Scott",
    _age: 24,
    _tel: 86247
};
//name属性为只读的
Object.defineProperty(person,"name",{
    get: function(){
        return this._name; 
    }
});
//age属性为只写不可读的
Object.defineProperty(person,"age",{
    set: function(p){
         this._age = p;
    }
});
//tel属性为可读可写的
Object.defineProperty(person,"tel",{
    get:function(){
         return this._tel;
    },
    set: function(p){
         this._tel = p;
    }
});
console.log(person.name);   //"Scott"
person.name = "Evan";
console.log(person.name);   //"Scott",对name属性的修改无效
console.log(person.age);    //undefined,不可读属性
person.age = 25;
console.log(person._age);   //25,已经修改
console.log(person.tel);    //"86247",可读属性
person.tel = "13975";
console.log(person.tel);    //"13975",可以修改

属性前面的下划线表示只能通过对象方法访问的属性。当我们使用person.name时实际上调用的是name属性的getter函数,为person.name赋值时调用的是name属性的setter函数,这样属性和访问器之间的关系就很清晰了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值