JavaScript 属性描述符简述

28 阅读2分钟

为什么要描述

onst user = {
  name: 'monica',
  age: 17
}

上面的对象,在JS内部被描述为

{
  // 属性 name 的描述符
  name: {
    value: 'monica',
    configurable: true, // 该属性的描述符是否可以被重新定义
    enumerable: true, // 该属性是否允许被遍历,会影响for-in循环
    writable: true // 该属性是否允许被修改
  },
  // 属性 age 的描述符
  age: {
    value: 'monica',
    configurable: true, // 该属性的描述符是否可以被重新定义
    enumerable: true, // 该属性是否允许被遍历,会影响for-in循环
    writable: true // 该属性是否允许被修改
  },
}
  • value : 成员的值
  • configurable :描述符是否可修改
  • enumerable :是否可被枚举
  • writable :是否可修改

描述 该方法允许对一个属性的描述进行检索。在 Javascript 中,属性 由一个字符串类型的“名字”(name)和一个“属性描述符”(property descriptor)对象构成。更多关于属性描述符类型以及他们属性的信息可以查看:Object.defineProperty.

获取描述符

Object.getOwnPropertyDescriptor(obj, propertyName)

该方法用于获取一个属性的描述符

const user = {
  name: 'monica',
  age: 17
}

Object.getOwnPropertyDescriptor(user, 'name');
/*
{
    value: 'monica',
    configurable: true, // 该属性的描述符是否可以被重新定义
    enumerable: true, // 该属性是否允许被遍历,会影响for-in循环
    writable: true // 该属性是否允许被修改
}
*/

定义描述符

Object.defineProperty(obj, propertyName, descriptor)

该方法用于定义某个属性的描述符

const user = {
  name: 'monica',
  age: 17
};

Object.defineProperty(obj, 'name', {
  value: 'jack', // 将其值进行修改
  enumerable: false, // 让该属性不能被遍历
  writable: false // 让该属性无法被重新赋值
})

getter setter

使用Object.definePorerty(obj,"name",{}) 也可以对 属性的访问和赋值进行限制

const obj = {};
Object.defineProperty(obj, 'a', {
  get(){ // 读取属性a时,得到的是该方法的返回值
    return 1;
  },
  set(val){ // 设置属性a时,会把值传入val,调用该方法
    console.log(val)
  }
})

console.log(obj.a); // 输出:1
obj.a = 3; // 输出:3
console.log(obj.a); // 输出:1

getter setter案例

// 遍历对象 user, 将其每一个属性变为 getter 和 setter, 保持读写功能不变
// 读取属性时,输出:正在读取xxx属性,值为xxx
// 给属性赋值时,输出:正在设置xxx属性,新的值为xxx
const user = {
	name: 'monica',
	age: 17,
	sex: 'female',
};

Object.entries(user).forEach(([key, value]) => {
	Object.defineProperty(user, key, {
		get() {
			console.log(`正在读取${key}属性,值为${value}`);
			return value;
		},
		set(val) {
			console.log(`正在设置${key}属性,新的值${val}`);
			value = val;
		},
	});
});

user.name
user.age = 12
//输出
//正在读取name属性,值为monica
//正在设置age属性,新的值12