随笔记录--JS中的数据属性和访问器属性

JS中有两种属性值:数据属性 和 访问器属性

一、数据属性

它包含着一个数据值的位置,在这可以对数据值进行读写

数据属性包含四个特性:

  • configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,默认值:true。
  • enumerable:表示是否可以通过for-in循环返回属性,默认值:true。
  • writable:表示能否修改属性的值,默认值:true。
  • Value:包含这个属性的值,默认值:undefined。

1.1 writable

var person = {};
Object.defineProperty(person,'name',{
    value: 'zhangsan'
})
person.name = 'Lisi';
console.log(person.name);  //zhangsan  
//发现value不能更改  因为defineProperty直接创建的属性writable默认为false,value值不可修改。


//修改writable为true

var person1 = {};
Object.defineProperty(person1,'name',{
    writable:true,
    value: 'zhangsan'
})
person1.name = 'Lisi';
console.log(person1.name);  //Lisi
//发现value可以被修改

使用Object.defineProperty直接创建的属性writable默认为false,value值不可以被修改。在这个时候如果修改name的值为Lisi,在非严格模式下是不会报错,仅仅是忽略该操作,但是在严格模式下就会报错。

修改数据属性的默认特性要用到一个方法:Object.defineProperty()方法,这个方法有三个参数:属性所在的对象,属性名,一个描述符对象。

1.2 Configurable

var person = {
    name: 'zhangsan',
    age: 20,
    sayName: function() {
        console.log(this.name);
    }
}
Object.defineProperty(person,"name",{
    configurable: false
})
delete person.name;  //操作被忽略,无法通过delete删除属性

Object.defineProperty(person,"name",{  //error
    configurable: true
})
Object.defineProperty(person, "name",{   //error
    enumerable:false    //enumerable默认值是true
})
//从上面可以看出属性的值是不能被改变的

Object.defineProperty(person,'name',{
    value: "wangwu"
})
console.log(person.name);  //wangwu
//由于writable为true,所以可以修改value

Object.defineProperty(person,"name",{
    writable: false   //// writable可进行true -> false的单向修改
})
Object.defineProperty(person,'name',{  //error
    value: "zhaoliu"   //writable已经被修改为false,故value不能被修改
})

Object.defineProperty(person,'name',{  //error
    writable: true     //此时writable不能被修改false->true
})

从上面可以看出
当configurable设置为false时

  • 不可以通过delete去掉该属性来重新定义属性
  • 不可以转换为访问器属性
  • configurable和enumerable不可以被修改
  • writable可以单向修改true-->false,但不可以修改false-->true。
    5.value的值能否被修改由writable来定,writable为true时value可以被修改,writable为false时value不能被修改。

注意:当configurable为false时,用delete删除属性,在非严格模式下只是忽略该操作,但不会报错,在严格模式下就会报错。其他不可被修改的操作无论是否在严格模式下都会报错。

1.3 Enumerable

enumerable表示对象属性是否可以在for...in和Object.keys()中被枚举。

var person = {}
Object.defineProperty(person,"num1",{
    value: 1    //enumerable defaults to false
})
Object.defineProperty(person,"num2",{
    value: 2,
    enumerable: false
})
Object.defineProperty(person,"num3",{
    value: 3,
    enumerable: true
})
person.num4 = 4;  //如果使用直接赋值的方式创建对象的属性,则这个属性的enumerable的默认值是 true

for(var num in person) {
    console.log(num);
}
//num3  num4

通过上面可以看出只有在enumerable为true 的时候餐才能通过for-in返回属性的值。

2.访问器属性

这个属性不包含数据值,包含的是一对get和set方法,在读写访问器属性时,就是通过这两个方法来处理的。

访问器属性包含四个属性

  • configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或能否把属性修改为访问器属性,默认为false
  • enumerable:表示能否通过for-in循环返回属性,默认为false
  • get:在读取属性时调用的函数,默认值为undefined
  • set:在写入属性时调用的函数,默认值为undefined
var book = {
    _year: 2020,  //下划线表示内部属性,只能通过对象的方法来读写
    editor: 2
}
console.log(book);


注意:访问器属性不能直接定义,要通过Object.defineProperty()这个方法来定义。
ECMAScript5中可以用Object.getOwnPropertyDescriptor()查看属性的特性。该方法接收两个参数:属性所在的对象名称和要读取特性的属性名称。

//通过Object.defineProperty()创建一个year属性
Object.defineProperty(book,'year',{
    get() {
        return this._year;
    },
    //若指定get不指定set,那就默认该属性是只读的
    set(newYear) {
        if(newYear !== this._year) {
            this._year = newYear;
            this.editor ++;
        }
    }
})
console.log(Object.getOwnPropertyDescriptor(book,"year"));
console.log("未修改:" + book.year);  
book.year = 2020;
console.log('修改后year的值:' + book.year);
console.log('修改year的之后,editor属性的值:' + book.editor); 

补充

1. Object.defineProperty()

通过object.defineProperty()可以直接修改对象上创建一个属性,也可以修改已有的属性。
这个方法有三个参数:
Object.defineProperty(obj, prop, descriptor)
属性所在的对象,属性名,一个描述符对象。
描述符对象包含六个属性:configurable、enumerable、writable、value、get、set ,要修改这些属性的特性,必须使用Object.defineProperty()方法。其他自定义的属性可以直接通过
【对象名】.【属性】 = 【修改的值】 来修改。
例如:person.name = "Lisi";
通过直接赋值的方式创建对象属性,其布尔值默认值是true,如果想通过Object.defineProperty来修改属性的特性时,只设置需要修改的特性值就可以了。
但是通过Object.defineProperty来创建的对象属性,其布尔值的默认值是false。

2.Object.defineProperties()

通过Object.defineProperties可以一次性对对象定义 多个属性。

var person = {};
Object.defineProperties(person, {
  name: {
    value: '小K哥',
    writable: true
  },
  _age: {
    value: 23,
    enumerable: true,
    writable: true,
    configurable: true
  },
  age: {
    get: function() {
            return this._age;
        },
        set: function(value) {
            this._age = value;
    }
  }
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。