轻松学习 JavaScript(7):对象属性描述符

2018/01/11 · JavaScript
· 对象

原文出处: Dhananjay
Kumar
   译文出处:码农网/小峰   

在JavaScript中,你可以如下所示创建一个对象字面量:

var cat = { name: ‘foo’, age: 9 };

1
2
3
4
var cat = {
    name: ‘foo’,
    age: 9
};

乍一看,好像对象cat有字符串和数字值这两个属性。然而,这不仅仅是JavaScript解释器。在ES5中,介绍了属性描述符的概念。在我们继续讨论属性描述符之前,让我们试着回答几个问题:

  • 如何创建只读属性?
  • 如何制定不可枚举的属性?
  • 如何使属性不可配置?
  • 如何确定一个属性是否是只读的?

如果你理解属性描述符,那么你就可以回答所有这些问题。

请看下面的代码:

var cat = { name: ‘foo’, age: 9 }; var a =
Object.getOwnPropertyDescriptor(cat, ‘name’); console.log(a);

1
2
3
4
5
6
var cat = {
    name: ‘foo’,
    age: 9
};
var a = Object.getOwnPropertyDescriptor(cat, ‘name’);
console.log(a);

输出将如下所示:

图片 1

正如你在这里看到的,这个属性有四个特征:

value保存属性的数据,而writable,enumerable和configurable则描述属性的其他特征。接下来我们将对这些特征一一阐述。

轻松学习 JavaScript——第 7 部分:对象属性描述符,javascript

在JavaScript中,你可以如下所示创建一个对象字面量:

var cat = {
  name: 'foo',
  age: 9
};

乍一看,好像对象cat有字符串和数字值这两个属性。然而,这不仅仅是JavaScript解释器。在ES5中,介绍了属性描述符的概念。在我们继续讨论属性描述符之前,让我们试着回答几个问题:

  • 如何创建只读属性?
  • 如何制定不可枚举的属性?
  • 如何使属性不可配置?
  • 如何确定一个属性是否是只读的?

如果你理解属性描述符,那么你就可以回答所有这些问题。

请看下面的代码:

var cat = {
    name: 'foo',
    age: 9
};
var a = Object.getOwnPropertyDescriptor(cat, 'name');
console.log(a);

输出将如下所示:

 
图片 2
image

正如你在这里看到的,这个属性有四个特征:

value保存属性的数据,而writable,enumerable和configurable则描述属性的其他特征。接下来我们将对这些特征一一阐述。

writable

属性的值是否可以更改是由writable特征决定的。如果writable设置为false,那么属性的值不能更改,JavaScript将忽略属性值中的任何更改。请看下面的代码:

var cat = { name: ‘foo’, age: 9 }; Object.defineProperty(cat, ‘name’, {
writable: false }); console.log(cat.name); // foo cat.name = “koo”; //
JavaScript will ignore it as writable is set to false
console.log(cat.name); // foo

1
2
3
4
5
6
7
8
var cat = {
    name: ‘foo’,
    age: 9
};
Object.defineProperty(cat, ‘name’, { writable: false });
console.log(cat.name); // foo
cat.name = "koo"; // JavaScript will ignore it as writable is set to false
console.log(cat.name); // foo

你可以使用Object.defineProperty更改writable、enumerable和configurable特征的值。我们稍后会在这篇文章中详细讨论Object.defineProperty,但正如你在上面的代码片段中看到的那样,我们已经将writable属性设置为false,从而改变了name属性的值。JavaScript将忽略重新分配,并且name属性的值将保持为foo。

如果以严格模式运行代码,那么为了重新分配writable设置为false的属性值,JavaScript将抛出异常。请看下面的代码:

‘use strict’; var cat = { name: ‘foo’, age: 9 };
Object.defineProperty(cat, ‘name’, { writable: false });
console.log(cat.name); // foo cat.name = “koo”; // error

1
2
3
4
5
6
7
8
‘use strict’;
var cat = {
    name: ‘foo’,
    age: 9
};
Object.defineProperty(cat, ‘name’, { writable: false });
console.log(cat.name); // foo
cat.name = "koo"; // error

在这里,JavaScript以严格模式运行,因此,当你重新分配name属性的值时,JavaScript将抛出异常,如下所示:

图片 3

这里的错误消息说,你不能赋值到只读属性。也就是说,如果属性的writable特征设置为false,那么属性将充当只读属性。

writable

属性的值是否可以更改是由writable特征决定的。如果writable设置为false,那么属性的值不能更改,JavaScript将忽略属性值中的任何更改。请看下面的代码:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { writable: false });
console.log(cat.name); // foo 
cat.name = "koo"; // JavaScript will ignore it as writable is set to false 
console.log(cat.name); // foo

你可以使用Object.defineProperty更改writable、enumerable和configurable特征的值。我们稍后会在这篇文章中详细讨论Object.defineProperty,但正如你在上面的代码片段中看到的那样,我们已经将writable属性设置为false,从而改变了name属性的值。JavaScript将忽略重新分配,并且name属性的值将保持为foo。

如果以严格模式运行代码,那么为了重新分配writable设置为false的属性值,JavaScript将抛出异常。请看下面的代码:

'use strict';
var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { writable: false });
console.log(cat.name); // foo 
cat.name = "koo"; // error

在这里,JavaScript以严格模式运行,因此,当你重新分配name属性的值时,JavaScript将抛出异常,如下所示:

 
图片 4
image

这里的错误消息说,你不能赋值到只读属性。也就是说,如果属性的writable特征设置为false,那么属性将充当只读属性。

configurable

属性的其他特征是否可以配置取决于configurable的值。如果属性configurable设置为false,则不能更改writable和enumerable的值。请看下面的代码:

var cat = { name: ‘foo’, age: 9 }; Object.defineProperty(cat, ‘name’, {
configurable: false }); Object.defineProperty(cat, ‘name’, { enumerable:
false });

1
2
3
4
5
6
var cat = {
    name: ‘foo’,
    age: 9
};
Object.defineProperty(cat, ‘name’, { configurable: false });
Object.defineProperty(cat, ‘name’, { enumerable: false });

在这里,我们将name属性的configurable设置为false。之后,我们将enumerable设置为false。如前所述,一旦一个属性的configurable设置为false,那么你就不能改变另一个特征。

对于上面的代码,JavaScript会抛出一个TypeError异常,如下图所示。你会得到无法重新定义属性名称的错误:

图片 5

在使用configurable的时候,你需要记住,改变configurable的值只能做一次。如果将属性的configurable设置为false,那么你就不能重新分配它;你无法撤消对configurable的更改。请看下面的代码:

var cat = { name: ‘foo’, age: 9 }; Object.defineProperty(cat, ‘name’, {
configurable: false }); Object.defineProperty(cat, ‘name’, {
configurable: true });

1
2
3
4
5
6
var cat = {
    name: ‘foo’,
    age: 9
};
Object.defineProperty(cat, ‘name’, { configurable: false });
Object.defineProperty(cat, ‘name’, { configurable: true });

我们在重新分配name属性的configurable,但是,JavaScript会对上述操作抛出一个TypeError,如下图所示。正如你所看到的,一旦configurable被设置为false,就不能撤销那个更改。

图片 6

另一个重要的事情是,即使configurable设置为false,writable也可以从true更改为false——但反之则不然。请看下面的代码:

var cat = { name: ‘foo’, age: 9 }; Object.defineProperty(cat, ‘name’, {
configurable: false }); Object.defineProperty(cat, ‘name’, { writable:
false }); cat.name = ‘koo’; console.log(cat.name); // foo

1
2
3
4
5
6
7
8
var cat = {
    name: ‘foo’,
    age: 9
};
Object.defineProperty(cat, ‘name’, { configurable: false });
Object.defineProperty(cat, ‘name’, { writable: false });
cat.name = ‘koo’;
console.log(cat.name); // foo

如果不是在严格模式下,上面的代码不会抛出任何异常。正如我们前面所讨论的,即使configurable为false,writable也可以从true变为false,反之则不然。另一个需要牢记的重要事项是,你无法删除configurable设置为false的属性。

var cat = { name: ‘foo’, age: 9 }; Object.defineProperty(cat, ‘name’, {
configurable: false }); delete cat.name; // wont delete as configurable
is false console.log(cat.name); // foo delete (cat.age); // will be
deleted console.log(cat.age); // undefined

1
2
3
4
5
6
7
8
9
var cat = {
    name: ‘foo’,
    age: 9
};
Object.defineProperty(cat, ‘name’, { configurable: false });
delete cat.name; // wont delete as configurable is false
console.log(cat.name); // foo
delete (cat.age); // will be deleted
console.log(cat.age); // undefined

在上面的代码中,你会发现JavaScript不会删除name属性,因为name属性的configurable设置为false。

configurable

属性的其他特征是否可以配置取决于configurable的值。如果属性configurable设置为false,则不能更改writable和enumerable的值。请看下面的代码:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
Object.defineProperty(cat, 'name', { enumerable: false });

在这里,我们将name属性的configurable设置为false。之后,我们将enumerable设置为false。如前所述,一旦一个属性的configurable设置为false,那么你就不能改变另一个特征。

对于上面的代码,JavaScript会抛出一个TypeError异常,如下图所示。你会得到无法重新定义属性名称的错误:

 
图片 7
image

在使用configurable的时候,你需要记住,改变configurable的值只能做一次。如果将属性的configurable设置为false,那么你就不能重新分配它;你无法撤消对configurable的更改。请看下面的代码:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
Object.defineProperty(cat, 'name', { configurable: true });

我们在重新分配name属性的configurable,但是,JavaScript会对上述操作抛出一个TypeError,如下图所示。正如你所看到的,一旦configurable被设置为false,就不能撤销那个更改。

 
图片 8
image

另一个重要的事情是,即使configurable设置为false,writable也可以从true更改为false——但反之则不然。请看下面的代码:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
Object.defineProperty(cat, 'name', { writable: false });
cat.name = 'koo';
console.log(cat.name); // foo

如果不是在严格模式下,上面的代码不会抛出任何异常。正如我们前面所讨论的,即使configurable为false,writable也可以从true变为false,反之则不然。另一个需要牢记的重要事项是,你无法删除configurable设置为false的属性。

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
delete cat.name; // wont delete as configurable is false 
console.log(cat.name); // foo 
delete (cat.age); // will be deleted
console.log(cat.age); // undefined

在上面的代码中,你会发现JavaScript不会删除name属性,因为name属性的configurable设置为false。