JS属性-------内部属性(数据属性和访问器属性)

本文详细介绍了JavaScript中的数据属性和访问器属性,包括它们的特性和使用方法。通过具体实例展示了如何利用Object.defineProperty()方法定制属性的行为,并介绍了如何批量定义属性。
摘要由CSDN通过智能技术生成

ECMA-262定义了内部才用的特性是为了实现JavaScript引擎用的,因此在JS中不能直接访问它们。

数据属性

可以获取和设置值的属性
数据属性包含了一个数据值的位置,在这个位置可以读取和写入值。也就是说,数据属性可以通过 对象.属性 访问,就是我么平常接触的用户赋什么值,它们就返回什么,不会做额外的事情。

数据属性有4个描述其行为的特性(为了表示内部值,把属性放在两对方括号中),称为描述符对象。

属性解释默认值
[[Configurable]]能否通过delete删除属性从而重新定义属性;
能否修改属性的特性;
能否把属性修改为访问器属性
true
[[Enumerable]]能否通过for-in循环返回属性true
[[Writable]]能否修改属性的值true
[[Value]]包含这个属性的数据值undefined

通过上述属性的默认值我们能看出我们能直接修改数据属性的属性特性,能用for-in循环返回属性,能修改属性的值,用undefined定义没有属性的数据值。这符合我们平常对对象属性的操作。

例子:

var person = {};
person.name='grace';
person.age=18;
console.log(person.name,person.age);   //结果:'grace 18'
person.name='alice';
console.log(person.name,person.age);   //结果:'alice 18'

但是如果已经给person.name赋过值了,我不希望再有人更改这个名字,因此需要调用person对象的内部属性,来控制对这个属性的操作权限。
要修改属性默认的特性,必须使用EM5的Object.defineProperty()方法。
格式

Object.defineProperty(属性所在的对象,属性的名字,一个描述符对象);  //可以创建数据属性(并设定其内部属性)

例子:设定名字属性不可修改

var person={};
Object.defineProperty(person,"name",{
  writable:false,                    //将能否修改属性的值设置为false,意思是不能修改person的name属性
  value:'grace'                      //将person的name默认属性设置为grace
})
person.age=18;
console.log(person.name,person.age);  //结果:'grace 18'
person.name='alice';
person.age=16;
console.log(person.name,person.age);  //结果:'grace 16'  此时无法修改name属性值

访问器属性

允许用户在赋值或取值都经过预先设定的函数,从而实现内部属性的那一种特殊效果
访问器属性不包含数据值,他们有一对儿getter和setter函数(不过这两个函数不是必须的)。

  • 在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值。
  • 在写入访问器属性时,会调用setter函数,这个函数负责决定如何处理数据。

访问器属性有如下4个特性:

属性解释默认值
[[Configurable]]能否通过delete删除属性从而重新定义属性;
能否修改属性的特性;
能否把属性修改为数据属性
true
[[Enumerable]]能否通过for-in循环返回属性true
[[Get]]在读取属性时调用的函数undefined
[[Set]]在写入属性时调用的函数undefined

要修改属性默认的特性,必须使用EM5的Object.defineProperty()方法。
格式

Object.defineProperty(属性所在的对象,属性的名字,一个描述符对象);  //也可以创建访问器属性

例子

var book = {
    _year : 2004,
    edition : 1
};
Object.defineProperty(book,"year",{ 
    get : function () {
        alert(this._year);
    },
    set : function (newValue) {
        if (newValue > 2004) {
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    }
});
book.year;      // 结果:2004
book.year = 2005;       //设置的属性要和defineProperty()函数里面的属性相同
console.log(book.edition);   // 结果:2

year 是 book 对象一个访问器属性。直接调用 book.year,即调用了这个访问器属性中定义的 get 方法(读取属性时调用),返回 book._year 这个数据属性。如果给 book.year 赋值,就是调用了这个访问器属性中定义的 set 方法(在写入属性时调用)。此时判断2005>2004,if条件为true,继续执行更改了_year属性值和edition属性值。
结论:数据属性不仅可以直接访问,也可以通过定义的访问器来专门访问。

定义多个属性

由于为对象定义多个属性的可能性很大,ECMAScript 5又定义了一个Object.defineProperties()方法。
格式

Object.defineProperties(添加和修改其属性的对象,{具体的属性})

例子:

var book={};

Object.defineProperties(book,{
 _year:{
   writable: true,
   value: 2004 
 },

 edition:{
   writable: true,
   value: 1
 },

 year: {
   get: function(){
     return this._year;
   },

   set: function(newValue){
     if (newValue>2004){
       this._year = newValue;
       this.edition += newValue - 2004;
     }
 }
})

以上代码在book对象上定义了两个数据属性(_year和 edition)和一个访问器属性(year)。

读取属性的特性

使用ECMAScript 5的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。
格式

Object.getOwnPropertyDescriptor(属性所在的对象,要读取其描述符的属性名称) //返回值是一个对象




参考文献:
https://www.zhihu.com/question/40648241?from=profile_question_card
https://segmentfault.com/q/1010000002664970

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值