JS对象中的属性类型、属性定义和属性读取

理解对象

ES5中的对象是指无序的属性的集合。(属性可以是基本值、对象和函数)。

对象的属性类型有两种,一种是数据属性,是数据值的保存位置;另一种是访问器属性,包含getter和setter函数。

1.1 数据属性

数据属性包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有四个描述其特征的特性。(这些特性是为javascript内部引擎服务的,不能直接访问,所以将它们放在方括号中。)

  1. [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。默认值为true。
  2. [[Enumerable]]: 能否通过for-in循环返回属性。默认值为true。
  3. [[Writable]]:能否修改属性的值,默认值为true。
  4. [[Value]]: 属性的数据值,默认为undefined。

!!!此处说的默认值是指直接定义时的默认值,与使用defineProperty()定义的属性默认值不同

数据属性可以直接使用对象字面量或new Object对象来定义,而这些特性值不能直接访问,要修改默认的特性,要使用定义在Object对象中的defineProperty()函数

!!!在调用 Object.defineProperty()方法时,如果不指定configurable、enumerable 和writable 特性的默认值都是 false。

示例如下:

// 使用对象字面量创建一个对象
var person = {
     };

//修改该对象属性的默认特性
/*
	第一个参数为属性所在的对象。
	第二个参数为要定义的属性名。
	第三个参数是其特性描述符的对象。(属性为configurable, enumerable, writable, value)
*/
Object.defineProperty(person, "name", {
      
 writable: false, 
 value: "Nicholas" 
});

//这样就可以访问定义好的数据属性了
alert(person.name); //"Nicholas" 

//在定义属性时将writable设定为false,所有对name属性的值更改操作无效。(严格模式下会报错)
person.name = "Greg"; 
alert(person.name); //"Nicholas"

另外将把 configurable 设置为 false,表示不能从对象中删除属性。如果对这个属性调用 delete,则在非严格模式下什么也不会发生,而在严格模式下会导致错误。一旦把属性定义为不可配置的,就不能再把它变回可配置了。 此时,Object.defineProperty()方法修改除 writable 之外的特性,都会导致错误。

1.2 访问器属性

访问器属性不包含数据值,包含一对 getter 和 setter 函数(不必需)。
在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;
在写入访问器属性时,会调用setter 函数并传入新值,这个函数负责决定如何处理数据。
访问器属性也包含了四个特性。

  1. [[Configurable]]: 表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。默认值为true。
  2. [[Enumerable]]: 能否通过for-in来访问属性。默认值为true。
  3. [[Get]]: 读取属性时调用的函数。默认值为undefined。
  4. [[Set]]:写入属性时调用的函数,默认值为undefined。

访问器属性不能直接定义,必须要使用Obiect.defineProperty()来定义。定义的过程于数据属性类似。

var book = {
      
 _year: 2004,  //'_'是一种常用于表示只能通过对象方法访问的属性的记号
 edition: 1 
}; 
/*
	第一个参数为属性所在的对象。
	第二个参数为要定义的访问器属性名。
	第三个参数是其特性描述符的对象。(属性为configurable, enumerable, get, set)
*/
Object.defineProperty(book, "year", {
      
// 访问一个私有变量
 get: function(){
      
 return this._year; 
 }, 
 // set常用于改变一个变量导致其他变量改变的情形
 set: function(newValue){
      
 if (newValue > 2004) {
      
 this._year = newValue; 
 this.edition += newValue - 2004; 
 } 
 } 
}); 
book.year = 2005; 
alert(book.edition); //2

不一定非要同时指定 getter 和 setter。
只指定 getter 意味着属性是不能写,在非严格模式下尝试写入属性会被忽略。
类似地,只指定 setter 函数的属性也不能读,在非严格模式下会返回 undefined。
在严格模式下,尝试写入只指定了 getter 函数的属性和读取只指定了 setter函数的属性会抛出错误。

定义多个属性

上面介绍的Object.defineProperty()方法只能定义单个属性,Object.defineProperties()方法可以通过描述符一次定义多个属性。
!!!在调用 Object.defineProperties()方法时,如果不指定configurable、enumerable 和writable 特性的默认值都是 false。
示例如下:

var book = {
     }; 
Object.defineProperties(book, {
      
	//定义数据属性
	 _year: {
      
	 	value: 2004 
	 }, 
	 edition: {
      
	 value: 1 
	 }, 
	 // 定义访问器属性
	 year: {
      
		 get: function(){
     
		 	return this._year; 
		 }, 
		 set: function(newValue){
      
			 if (newValue > 2004) {
      
			 this._year = newValue; 
			 this.edition += newValue - 2004; 
		 	} 
	 	} 
	} 
});

读取属性的特性

JS中的Object。getOwnPropertyDescriptor()方法可以取得给定的对象属性描述符。对上一节中定义的book对象,有以下示例:

// 该方法接受两个参数  第一个参数是对象   第二个参数是对应的属性
var descriptor = Object.getOwnPropertyDescriptor(book, "_year"); 
alert(descriptor.value); //2004 
alert(descriptor.configurable); //false
alert(typeof descriptor.get); //"undefined" 

var descriptor = Object.getOwnPropertyDescriptor(book, "year"); 
alert(descriptor.value); //undefined 
alert(descriptor.enumerable); //false 
alert(typeof descriptor.get); //"function"

在 JavaScript 中,可以针对任何对象——包括 DOM 和 BOM 对象,使用 Object.getOwnPropertyDescriptor()方法。

你可能感兴趣的:(javascript,js对象,js对象属性,Js属性描述符)