1. 数据属性

# 1. 数据属性

# [[Configurable]]

表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,是否可以把它改为访问器属性

# [[Enumberable]]

表示属性是否可以通过for-in循环返回

# [[Writable]]

表示能否修改属性的值

# [[Value]]

包含属性实际的值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置

默认值为undefined

# 1.1 在对象上定义

let person = {
	name: "YK菌"

直接在对象上定义的属性,它们的[[Configurable]]、[[Enumerable]]和[[Writable]]特性都被设置为true,而[[Value]]特性被设置为指定的值

# 1.2 使用Object.defineProperty()方法设置属性默认特性

let person = {};
Object.defineProperty(person, "name", {
	writable: false,
	value: "Nicholas"
});
console.log(person.name); // "Nicholas"
person.name = "Greg";
console.log(person.name); // "Nicholas"
let person = {};
Object.defineProperty(person, "name", {
	configurable: false,
	value: "Nicholas"
});
// 抛出错误
Object.defineProperty(person, "name", {
	configurable: true,
	value: "Nicholas"
});

在调用Object.defineProperty()时,configurable、enumerable 和writable 的值如果不指定,则都默认为false

# 2. 访问器属性

访问器属性不包含数据值。相反,它包含一个获取getter函数和一个设置setter函数

# [[Configurable]]

表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,是否可以把它改为访问器属性

直接在对象上定义的属性,默认值为true

# [[Enumberable]]

表示属性是否可以通过for-in循环返回

直接在对象上定义的属性,默认值为true

# [[Get]]

在读取属性时调用的函数

默认值为undefined

# [[Set]]

在写入属性时调用的函数

默认值为undefined

  • 访问器属性不能直接定义,必须使用Object.defineProperty()方法

# 2.1 定义私有成员,设置get、set方法

// 定义一个对象,包含伪私有成员year_和公共成员edition
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
  • year_中的下划线常用来表示该属性并不希望在对象方法的外部被访问。
  • 另一个属性year 被定义为一个访问器属性,其中获取函数返回year_的值,而设置函数会做一些计算以决定正确的版本(edition)。
  • 这是访问器属性的典型使用场景,即设置一个属性值会导致一些其他变化发生。

  • 获取函数和设置函数不一定都要定义。只定义获取函数意味着属性是只读的,尝试修改属性会被忽略。
  • 类似地,只有一个设置函数的属性是不能读取的。

# 3. 设置多个属性 Object.defineProperties()

在book 对象上定义了两个数据属性year_和edition,还有一个访问器属性year

let book = {};
Object.defineProperties(book, {
	year_: {
		value: 2017
	},
	edition: {
		value: 1
	},
	year: {
		get() {
			return this.year_;
		},
		set(newValue) {
			if (newValue > 2017) {
				this.year_ = newValue;
				this.edition += newValue - 2017;
			}
		}
	}
});

# 4. 读取属性的特性Object.getOwnPropertyDescriptor()

  • 使用ECMAScript 5的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。
  • 这个方法接收两个参数:属性所在的对象和要读取其描述符的属性名称
  • 返回值是一个对象,对于访问器属性包含configurable、enumerable、get 和set 属性,对于数据属性包含configurable、enumerable、writable 和value 属性
let book = {};
Object.defineProperties(book, {
	year_: {
		value: 2017
	},
	edition: {
		value: 1
	},
	year: {
		get: function() {
			return this.year_;
		},
		set: function(newValue){
			if (newValue > 2017) {
				this.year_ = newValue;
				this.edition += newValue - 2017;
			}
		}
	}
});
let descriptor = Object.getOwnPropertyDescriptor(book, "year_");
console.log(descriptor.value); // 2017
console.log(descriptor.configurable); // false
console.log(typeof descriptor.get); // "undefined"

let descriptor = Object.getOwnPropertyDescriptor(book, "year");
console.log(descriptor.value); // undefined
console.log(descriptor.enumerable); // false
console.log(typeof descriptor.get); // "function"
  • ECMAScript 2017 新增了Object.getOwnPropertyDescriptors()静态方法
let book = {};
Object.defineProperties(book, {
	year_: {
		value: 2017
	},
	edition: {
		value: 1
	},
	year: {
		get: function() {
		return this.year_;
	},
		set: function(newValue){
			if (newValue > 2017) {
				this.year_ = newValue;
				this.edition += newValue - 2017;
			}
		}
	}
});
console.log(Object.getOwnPropertyDescriptors(book));
// {
// edition: {
// 	configurable: false,
// 	enumerable: false,
// 	value: 1,
// 	writable: false
// },
// year: {
// 	configurable: false,
// 	enumerable: false,
// 	get: f(),
// 	set: f(newValue),
// },
// year_: {
// 	configurable: false,
// 	enumerable: false,
// 	value: 2017,
// 	writable: false
// }
// }
上次更新: 2022/4/21 22:21:34