Object.defineProperty设置对象属性

8.1.1 属性的类型

  建议观看一个教学视频再看下面内容更容易理解:Object.defineProperty

  ECMAScript 中有两种属性:数据属性访问器属性

  • 数据属性

  数据属性是用来保存数据的,其中有 4 个描述其行为的特性,其中有一个特性 [[Value]] 是存放值的位置,这个位置可以读取和写入设置的属性的值。四个特性如下:

① [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

② [[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

③ [[Writable]]:表示能否修改属性的值。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

④ [[Value]]包含这个属性的数据值。读取属性值的时候从这个位置读;写入属性的时候,把新值保存在这个位置。这个特性的默认值为 undefined。

  要修改属性的默认的特性,必须使用 ECMAScript5 中的 Object.defineProperty() 方法。这个方法接收三个参数:属性所在的对象属性的名字、和一个描述符对象。其中,描述符对象的属性必须是:configurable、enumerable、writable 和 value。设置其中一个或多个值。例如:

var person = {};
Object.defineProperty(person,"name",{
    writable: false,        // 设置"name"属性的 writable 特性值为 false,
    value: "andy"
});
alert(person.name);         // andy
person.name = "Grey";       // 尝试修改属性值,无效
alert(person.name);         // andy,不可修改的属性

  上述第7行代码在非严格模式下被忽略,在严格模式下报错。【注意】,①一旦使用 Object.defineProperty() 方法,如果没有指定特性的值,configurable、enumerable 和 writable 特性的默认值都是 false 【注意与在对象上定义属性时,特性的默认值不同】。②在 configurable 设置为 false 之前是可以多次调用 Object.defineProperty() 方法去设置同一个属性值的特性的,一旦 configurable 设置为 false 之后,就不允许在调用 Object.defineProperty() 方法去设置属性特性。严格模式下会报错。

"use strict";
let person = {};
Object.defineProperty(person,"name",{
    writable: false,        
    value: "andy"
});
// 下一行代码报错,因为第三行方法中为 configurable 特性设置了 false 值。
Object.defineProperty(person,"name",{
    value: "jack"
});

  或者使用 Object.defineProperties(obj, props) 一次定义多个新的属性或修改多个现有属性,并返回该对象。

let obj = {};
Object.defineProperties(obj, {
  'property1': {
    value: true,
    writable: true
  },
  'property2': {
    value: 'Hello',
    writable: false
  }
  // etc. etc.
});

  数据属性其实就是更加底层的设置属性的方法,可以对属性进行更加细微的设置,可以完全用数据属性的方法为一个对象设置相关属性。

  • 访问器属性

  访问器属性不包含数据值。它们包含一个获取 (getter) 函数和一个设置 (setter) 函数,不过这两个函数不是必需的。在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。访问器属性有 4 个特性描述它们的行为。

① [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。该特性的默认值都是 true。

② [[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

③ [[Get]]:获取函数,在读取属性时调用。默认值为 undefined。

④ [[Set]]:设置函数,在写入属性时调用。默认值为 undefined。

  访问器属性是不能直接定义的,必须使用 Object.defineProperty()。下面是一个例子:

let book = {
	year_:2017,
	edition:1
};
Object.defineProperty(book,"year",{
	get() {
		return this.year_;
	},
	set(newValue){
		if(newValue > 2017){
			this.year_ = newValue;
			this.edition += newValue - 2017;
		}
	}
});
book.year = 2018;
console.log(book.edition);	// 2

  获取函数和设置函数不一定都要定义。只定义获取函数意味着属性是只读的,尝试修改属性会被忽略。在严格模式下,尝试写入只定义了获取函数的属性会抛出错误。类似地,只有一个设置函数的属性是不能读取的,非严格模式下读取会返回 undefined,严格模式下会抛出错误。

  建议看完上面讲解再看一遍视频加深理解理解:Object.defineProperty

你可能感兴趣的:(#,JavaScript,前端,javascript,前端)