在使用js的Object.defineProperty来给一个对象定义属性时,为什么没有设置writable,configurable,enumerable为false,却改变不了它的value和读出它的属性名?
首先,我们了解一下Object.defineProperty的四个数据属性
configurable: 仅当该属性的 configurable 为 true 时,该属性才能够被改变,也能够被删除。默认为 false
enumerable :仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
writable: 仅当仅当该属性的writable为 true 时,该属性才能被赋值运算符改变。默认为 false
value: 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined
接着,我们来看一下代码。
var person={};
Object.defineProperty(person,"name",{
value:'Margot'
});
console.log(person.name); //Margot
console.log(Object.keys(person)); // []
1
2
3
4
5
6
7
8
9
这是因为,在调用Object.defineProperty()方法创建一个新的对象属性时,如果不指定,writable,configurable,enumerable三个特性的默认值都为false,所以我们无法对它的属性进行更改、写入和循环返回出属性名。
另外,我们要知道,在非严格模式下,person.name='Alice'; delete person.name;这行赋值会被忽略;在严格模式下,会导致抛出错误。
但如果我们用var定义person的时候就给了一个name属性,也就是说调用Object.defineProperty()方法只是修改已定义的属性的特性时,就可以正常更改、写入和循环返回了。如下所示
因为configurable,writeable,enumerable默认为true
var person={
name:'Mike'
};
Object.defineProperty(person,"name",{
value:'Margot'
});
console.log(person.name); //Margot
person.name='Alice';
console.log(person.name); //Alice
首先,我们了解一下Object.defineProperty的四个数据属性
configurable: 仅当该属性的 configurable 为 true 时,该属性才能够被改变,也能够被删除。默认为 false
enumerable :仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
writable: 仅当仅当该属性的writable为 true 时,该属性才能被赋值运算符改变。默认为 false
value: 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined
接着,我们来看一下代码。
var person={};
Object.defineProperty(person,"name",{
value:'Margot'
});
console.log(person.name); //Margot
person.name='Alice';
delete person.name;
console.log(person.name); //Margotconsole.log(Object.keys(person)); // []
1
2
3
4
5
6
7
8
9
这是因为,在调用Object.defineProperty()方法创建一个新的对象属性时,如果不指定,writable,configurable,enumerable三个特性的默认值都为false,所以我们无法对它的属性进行更改、写入和循环返回出属性名。
另外,我们要知道,在非严格模式下,person.name='Alice'; delete person.name;这行赋值会被忽略;在严格模式下,会导致抛出错误。
但如果我们用var定义person的时候就给了一个name属性,也就是说调用Object.defineProperty()方法只是修改已定义的属性的特性时,就可以正常更改、写入和循环返回了。如下所示
因为configurable,writeable,enumerable默认为true
var person={
name:'Mike'
};
Object.defineProperty(person,"name",{
value:'Margot'
});
console.log(person.name); //Margot
person.name='Alice';
console.log(person.name); //Alice
console.log(Object.keys(person)); // [ 'name' ]
一个对象book,有个属性year,但是如果让用户随便一个book.year=-1;这样的话可不好啊,于是乎,book定义的year前面加了个_,表示是私有的,对于用户来说也不会知道有这么个变量,用户只会知道year,Object.defineProperty里面定义了“year”这个属性,也就是说,如果用户book.year,那么一般会返回对应的值,这里就会调用get函数,返回去的是_year值,用户来看就是book.year返回了2004,实际上内部用了get函数返回的是_year值;如果用户book.year=2017;那么实际上调用了set函数,将_year改成2017,这样用户再调用book.year就是2017了。
为什么非得加个get和set函数呢?
因为,这样增加了判断,如果set值为-1这样不是正常年份的值,那么就可以报错或者其他的,不让用户设置成功。
同时也避免了用户不小心设置错了值的情况。。