ES5擴展了Object對象的接口,增加了幾個特別的函數,可以在程序運行時影響解釋器的行為。如:defineProperty,seal,freeze...等等。
實際上這些函數改變的是對象的內部狀態,解釋器在解釋對象時會根據他的內部狀態改變自己的行為,這些狀態被稱為特性(attribute)。
ES5能直接操作對象的屬性描述,一個普通屬性擁有四種特性。
* value。訪問屬性時的值。
* writable。表示屬性value的可寫性。
* enumerable。表示屬性可枚舉。
* configurable。表示屬性描述可配置。
使用getOwnPropertyDescriptor函數可以獲取屬性的描述。
~~~
var foo = { a: 0 };
var desc = Object.getOwnPropertyDescriptor(foo, 'a');
console.dir(desc);
~~~

可見除了value被設置了,其他特性默認值為true。
通過defineProperty或defineProperties可以定義或修改屬性的描述。如
~~~
var foo = {};
Object.defineProperties(foo, {
a: {
value: 0,
writable: false,
}
});
console.dir(foo);//{a:0}
foo.a = 666;
console.dir(foo);//{a:0}
~~~
可見,當writable為false時,該屬性就不可寫。
ES5內置的其他特性也會影響解釋器的行為,具體此處不再詳述。
# 訪問器屬性
在ES5還提供了一種叫訪問器的屬性,而之前ES默認使用的屬性被稱為數據屬性。
訪問器屬性的描述有四種特性。
* get。獲取屬性值時觸發的函數。
* set。設置屬性值時觸發的函數。
* enumerable。表示屬性可枚舉。
* configurable。表示屬性的可配置。
事實上,我們可以把訪問器屬性看作是特殊的函數,不過一個屬性有可能被分為兩個函數。
~~~
var foo = {};
Object.defineProperties(foo, {
a: {
set: function (v) {
console.info('set');
console.dir(v);
},
get: function () {
return 'get';
}
}
});
foo.a = 123;
console.info(foo.a);
~~~

# 以屬性描述為起點
在一些高級語言里,也有特性的概念。如C#的特性,JAVA的注解,他們也能在運行時影響解釋器的行為。而C#/JAVA中的特性更為強大,不僅能描述屬性,還能描述類,描述函數……等等,又或是添加自定義的特性,在運行中反射特性為自己所用,卻可以不改變已有代碼的結構。這也是所謂的AOP(面向切面編程)。
目前來說,ES的特性(attribute)只有一些簡單的功能,但可以想象的是,ES未來發展一定會逐步完善特性。