JavaScript对象中的可枚举属性和不可枚举属性

在JavaScript中,对象的属性有可枚举和不可枚举之分,它是由对象属性描述符enumerable决定的。如果该属性是可枚举性的那么这个属性就能被for…in查找遍历到。

对象的属性描述符

在JavaScript中可以通过Object.defineProperty()来为对象设置属性描述符。

从ES5开始,添加了对对象属性描述符的支持。现在JavaScript中支持6种属性描述符:

  • configurable:设为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
  • enumerable: 设置为true的时候该属性才会出现在对象的枚举属性中。
  • value: 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等),默认值undefined
  • writable: 设置为true的时候,value才能被赋值运算符改变。改变。
  • get : 属性的 getter 函数。当访问该属性时,才会调用此函数,执行时不传入任何参数,但是会传入 this 对象。该函数的返回值会被用作属性的值。默认值undefined
  • set:属性的 setter 函数。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。默认值undefined
Object.defineProperty()
Object.defineProperty(obj, prop, descriptor)

使用Object.defineProperty()定义属性

  • 通过Object.defineProperty()定义的属性,enumerable,configurable,writable这几个值默认为false

  • 直接为对象动态添加属性,enumerable,configurable,writable这几个值默认为true

let cat ={name:'猫'}
Object.defineProperty(cat, "sound", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "喵喵"
});

//对象动态添加属性
cat.age=2

哪些是可枚举属性?

  • enumerable:true的属性即为可枚举属性
  • 基本包装类型的原型属性都是不可枚举的,如Object, Array, Number等

直观看到可枚举属性

谷歌浏览器控制台查看对象属性,深色的属性就是可枚举属性,浅色的属性就是不可枚举属性。
在这里插入图片描述

与枚举属性有关的几个方法

  • Object.getOwnPropertyNames() 获取对象自身所有的属性键名,包括可枚举和不可枚举的属性。
  • Object.keys()获取对象自身的可枚举属性键名,返回键名数组。
  • obj.propertyIsEnumerable()判断对象实例obj自身的属性是否为可枚举。
  • for...in 遍历对象自身的和原型链上的可枚举的属性。可配合hasOwnProperty()只获取自身可枚举属性
  • Object.values()获取对象自身的可枚举属性的值,返回值数组。
  • Object.entries()获取对象自身的可枚举属性的键值对,每个键值对以数组的形式存储,返回键值对数组集。

以上几个方法除了for...in外其他的方法都无法遍历到原型链的属性。

  • Reflect.ownKeys()获取对象自身所有的属性键名,包括Symbol类型属性
  • Object.getOwnPropertySymbols()获取对象自身Symbol类型属性
    Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。

属性枚举与否有何用?

设置为不可枚举后,for...in 就无法获取到对象上对应的属性。比如有些场景下你不希望这个属性被获取到。

在这里插入图片描述
🌰Object.defineProperty()定义的属性默认不可枚举
🌰Object.getOwnPropertyNames()获取对象自身所有的属性键名

let cat ={name:'猫'}
 Object.defineProperty(cat, "sound", {
   // enumerable: false,
   // configurable: false,
   // writable: false,
   value: "喵喵"
 });

 console.log(cat.propertyIsEnumerable('sound'))//false
 console.log(Object.getOwnPropertyNames(cat));//["name", "sound"]

🌰Object.keys()只能获取自身的可枚举属性(无法获取原型链上的)

function Person(name,age){
	this.name=name;
	this.age=age;
}
Person.prototype.country='CN';

var Joe=new Person('Joe',24)
Object.defineProperty(Joe,'city',{
  value: 'GZ',
  enumerable:true
})


console.log(Object.keys(Joe));
console.log(Object.values(Joe));
console.log(Object.entries(Joe));

在这里插入图片描述

🌰 for...in 遍历对象自身的和原型链上的可枚举的属性。

let Joe = new Person();
Joe.name = 'Joe';
function Person(){}
Person.prototype._age = 24;

const for_in_keys = (()=>{
	let keysArray=[];
	return ()=>{
		for (let key in Joe) {
			keysArray.push(key)
		}
		return keysArray;
	}
})()

console.log(for_in_keys());//["name", "_age"]

🌰遍历Symbol属性值

let sb=Symbol();

let a={name:'Joe'}

a[sb]='1'
console.log(a[sb]);
console.log({key:Object.keys(a),sym:Object.getOwnPropertySymbols(a),all:Reflect.ownKeys(a)});

在这里插入图片描述

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值