JS中常说的“可枚举”是什么意思?

“可枚举”,即,可以被遍历或列举出来

可枚举意味着可以被遍历或列举出来。在不同的领域和上下文中,可枚举的概念有不同的应用和解释。

1、在计算机编程中,特别是JavaScript中,可枚举属性是指那些内部“可枚举”标志设置为true的属性,这些属性可以通过for...in循环进行遍历。如果一个属性的enumerable为false,那么该属性不会被包括在for...in循环中。‌

2、在编程中,可枚举类型是那些带有GetEnumerator方法的类型,可以是类、数组、接口等,它返回一个枚举器。‌

综上所述,可枚举的概念根据应用场景的不同而有所不同,但核心意义在于能够被遍历或列举出来。


​可枚举性是‌JavaScript中属性的一种特性,决定了该属性是否能被for...in循环、Object.keys()方法或JSON.stringify()方法访问到。属性的可枚举性由其enumerable属性决定,如果设置为true,则属性是可枚举的;如果设置为false,则属性是不可枚举的。

一、如何判断属性是否可枚举

使用Object.prototype.propertyIsEnumerable()方法可以判断一个对象是否包含某个属性,并且这个属性是否可枚举。如果属性存在于对象的原型内,不管它是否可枚举都会返回false

对象的属性是否具有可枚举属性是由enumerable值决定;

可以通过obj.propertyIsEnumerable(prop);来判断obj对象的prop属性是否能够枚举,该方法返回的是一个布尔值,表示指定的属性是否可枚举。但是在原型链上propertyIsEnumerable不被考虑。

语法:obj.propertyIsEnumerable(prop)

描述:每个对象都有一个propertyIsEnumerable方法。此方法可以确定对象中指定的属性是否可枚举,返回一个布尔值。但该方法对通过原型链继承的属性无效(原型链继承的属性是否可枚举不能用该方法来判断)。
 

注意:判断一个属性是否可枚举,用Object.propertyIsEnumerable()来判断,但需要注意的一点是如果需要判断的属性在object的原型链上,不管它是否可枚举,Object.propertyIsEnumerable()都会返回false


延伸:hasOwnProperty()方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性

案例:用户自定义对象和引擎内置对象的区别

Math.propertyIsEnumerable('random');   // 返回 false
Object.propertyIsEnumerable('constructor');    // 返回 false
var num = new Number();
for(var pro in num) {
    console.log("num." + pro + " = " + num[pro]);
}//输出空

这说明了开发者自定义的属性在一般情况下时可以枚举的,但是内置的对象Math和基本包装类型里的属性是不可枚举的,如Object, Array, Number等;其实,propertyIsEnumerable方法只对对象自身的属性(对象自身添加的、构造函数实例化的)有效,对原型上的、继承来的属性都无效。

二、如何设置可枚举属性(enumerable)

使用Object.defineProperty()或 Object.defineProperties()方法设置属性对象的enumerable属性为true即可。 

■ 参考:JS中的可枚举属性与不可枚举属性

var person = {
    name:'xiao',
    age: '18',
    sex: 'boy'
}
 
Object.defineProperty(person,'age',{
    enumerable:true,//可以被枚举
});
Object.defineProperty(person,'sex',{
    enumerable:false,//不可以被枚举
})
 
for(var k in person){
    console.log(person[k])//a,可以被枚举
}
//18
//xiao

​Object.defineProperty(obj, prop, descriptor)方法有三那个参数

第一个:目标对象;第二个:目标属性,字符串;第三个:对目标属性的行为,放在对象里

enumerable为true时表示可枚举,enumerable为false表示不可枚举;

开发者自己定义的对象person中的所有属性默认都是可枚举的; ​

如何查看ES5标准下的属性的缩微小对象?可以使用 Object.getOwnPropertyDescriptor(obj, prop) 方法获取属性的描述对象,从而判断属性是否可枚举。 

番外:基本包装类型和引用类型的原型属性的可枚举性

基本包装类型的原型属性(如String, Number, Boolean等)可以枚举。‌

在JavaScript中,‌对象的属性是否可以被枚举,‌即是否可以通过for...in循环或其他遍历方法被遍历到,‌主要取决于该属性的可枚举性。‌基本包装类型的原型属性,‌如果被定义为可枚举,‌那么它们就可以被遍历。‌例如,‌通过Object.keys()方法或JSON.stringify()方法,‌只能返回和序列化对象本身的可枚举属性。‌这意味着,‌如果基本包装类型的原型属性被设置为可枚举,‌那么它们将能够被这些方法检测到并处理。| JS中的枚举和不可枚举 - 简书

然而,‌需要注意的是,‌不是所有的属性都是可枚举的。‌有些属性可能被设置为不可枚举,‌这意味着它们不会被for...in循环或其他遍历方法遍历到。‌这种设置通常用于隐藏某些内部属性或方法,‌以避免它们被意外地访问或修改。‌

总的来说,‌基本包装类型的原型属性的可枚举性取决于它们的定义。‌如果这些属性被设置为可枚举,‌那么它们就可以被遍历和处理。‌

参考:JS中的基本包装类型有哪些?JS中的枚举和不可枚举 - 简书

引用类型的原型属性(如Object, Array等)通常被设置为不可枚举,因此,不能通过for...in循环访问到。

在编程中,‌引用类型的原型属性通常指的是对象的原型上定义的属性和方法,‌这些属性和方法可以被所有通过该原型创建的对象继承。‌然而,‌这些原型属性并不能直接被枚举,‌因为它们不是直接附加到对象实例上,‌而是通过原型链继承得到的。‌因此,‌尝试枚举引用类型的原型属性通常没有直接的方法来实现,‌除非是通过遍历对象的原型链来逐一检查其属性,‌但这并不是一个标准的操作,‌且可能因语言和环境的差异而有所不同。‌

在JavaScript等语言中,‌对象的原型(‌prototype)‌属性通常用于存储共享的方法和属性,‌而不是用于枚举的。‌枚举通常指的是对一组固定的、‌预定义的值进行遍历或选择,‌而这些值通常是作为枚举类型的一部分在代码中明确声明的。‌因此,‌引用类型的原型属性并不符合枚举的定义,‌也无法通过标准的枚举方法来列出或访问。‌

此外,‌对于某些编程语言中的特定情况,‌如C#中的枚举类型,‌虽然可以定义枚举成员来表示选项组合,‌并通过位字段和位运算来处理这些选项的组合和分离,‌但这与引用类型的原型属性的枚举是两个不同的概念。‌在C#中,‌枚举类型的设计是为了表示一组固定的、‌预定义的值,‌而不是为了枚举对象的原型属性1。‌

综上所述,‌引用类型的原型属性通常不能被枚举,‌因为它们是通过原型链继承得到的,‌而不是直接附加到对象实例上的属性。‌尝试枚举这些属性通常需要遍历原型链,‌但这并不是一个标准的操作,‌且可能因语言和环境的差异而有所不同

三、枚举性的作用

属性的可枚举性会影响for...in循环、Object.keys()方法和JSON.stringify()方法的结果。例如,通过Object.defineProperty()或 Object.defineProperties()定义的不可枚举属性不会出现在通过for...in循环的遍历结果中。

引入可枚举性这个概念的最初目的是为了让某些属性可以规避掉for...in操作,不然内部属性和方法都会遍历到

四、获取所有属性,包括不可枚举属性

使用Object.getOwnPropertyNames()方法可以获取对象的所有属性,包括不可枚举的属性。这个方法返回一个包含对象自身所有属性的数组(包括不可枚举的属性),但不包括Symbol类型的属性。

■ for...in循环是 遍历对象的每一个可枚举属性,包括原型链上面的可枚举属性

for…in循环可以枚举(遍历)出对象本身具有的属性,通过Object.defineProperty()方法加的可枚举属性,或者通过原型对象绑定的可以枚举属性。

■ 而Object.keys(obj)只是遍历自身的可枚举属性,不可以遍历原型链上的可枚举属性。这是for...in 和 Object.keys()的主要区别。另外,注意它同for...in一样不能保证属性按对象原来的顺序输出。


也就是说,Object.keys()方法可以枚举实例对象本身的属性和通过Object.defineProperty()添加的可枚举属性,即不会枚举原型链上的属性

■ Object.getOwnPropertyNames()则是遍历自身所有属性(不论是否是可枚举的),不包括原型链上面的。

JSON.stringify()方法只能序列化实例对象本身的属性和通过Object.defineProperty()添加的可枚举属性为JSON对象,即不会序化原型链上的属性

参考:JS中的枚举和不可枚举 - 简书 | 可枚举属性、可迭代对象、迭代器(iterator)-CSDN

通过了解这些,开发者可以更好地控制对象的属性和它们的行为,特别是在需要隐藏某些属性或控制属性显示时机的情况下。例如,在创建对象时,可以通过设置属性的enumerable值为false来确保该属性不会被外部代码轻易访问或修改,从而增加代码的安全性和封装性。‌


参考资料

枚举和不可枚举 - 简书 | JS中的枚举和不可枚举 - 简书

可枚举属性、可迭代对象、迭代器(iterator)-CSDN博客

JS方法中可枚举和不可枚举什么意思-CSDN | JS中的可枚举属性与不可枚举属性-博客园

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

儒雅的烤地瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值