美文网首页js
JavaScript 中的枚举属性 enumeration

JavaScript 中的枚举属性 enumeration

作者: liwuwuzhi | 来源:发表于2017-12-01 18:49 被阅读0次

先把总结写在这里:

  1. JavaScript对象的属性可分为可枚举和不可枚举,它是由属性的 enumeration 值决定的,true 为可枚举,false为不可枚举
  2. 原生构造函数(Boolean, Number, String 等)的内置属性(例如 toSring、 constructor等) 和 引擎内置对象的属性(Math 的 random 等) 一般是不可枚举的,而自己定义的属性(不管是原型上的还是自身的)一般是可枚举的。
  3. 属性的枚举性会影响以下四个方法的结果
    1) for...in
    2 )Object.keys()
    3) JSON.stringify()
    4) Object.assign()

小结:

  • 这四个方法中,只有 for/in 是对所有可枚举属性(对象本身的可枚举属性,以及从其构造函数原型中继承的可枚举属性),而其他三种是对自身可枚举属性才有效。
  • 而四个方法中又只有 Object.assign() 对 Symbol 属性有效,其他三种对 Symbol 都会过滤掉。
    这里做一个其他的小总结:
  • 上面四个方法中,其中Object.assign()无法正确拷贝get属性和set属性,而 JSON.stringify()对对象的方法、undefined值、get 属性、set属性无效 。
  • 如果该参数不是对象,则会先转成对象,然后返回。
    由于undefined和null无法转成对象,所以如果它们作为(第一个)参数,就会报错。有这两种特性的方法是:
    Object.assign() 、 Object.setPrototypeOf()、Object.getPrototypeOf()



上面说了JavaScript对象的属性是否可枚举是 enumeration 的值决定的,那么enumeration是什么时候怎么去设置的呢?
enumeration 是 Object.defineProperty() 方法的一个参数,下面来看看怎么去设置 一个属性是否可枚举。

var person = {
    name:'zhou',
    age: '12',
    sex: 'girl'
}

Object.defineProperty(person,'age',{
    enumerable:true,//可以被枚举
});
Object.defineProperty(person,'sex',{
    enumerable:false,//可以被枚举
})

for(var k in person){
    console.log(person[k])//a,可以被枚举
}
//12
//zhou

如何设置是否可枚举-- enumerable

由上面的点可以看出:
1.Object.defineProperty(obj, prop, descriptor)方法有三个参数,每个参数各代表着
  第一个:目标属性所在的对象,
  第二个:目标属性,放在字符串里,
  第三个:目标属性的行为,放在对象里;
2.enumerable为true表示可枚举,enumerable为false表示不可枚举;
3.开发者自定义的对象person的所有属性都是可枚举的;

如何判断是否可枚举-- obj.propertyIsEnumerable()

在不知情的情况下,如何判断一个属性是否可枚举呢?obj.propertylsEnumerable()方法可以解决这个问题。

  1. 语法:obj.propertyIsEnumerable(prop)
  2. 定义:每个对象都有一个propertyIsEnumerable方法,表示指定的自身属性是否可枚举 (继承属性无效) ,返回一个布尔值(当对象没有该指定属性时也返回 false)。
  3. 用法:
    1)就上面的例子的使用
person.propertyIsEnumerable('name');//true
person.propertyIsEnumerable('age');//true
person.propertyIsEnumerable('sex');//false

2)引擎内置对象的属性不可枚举

var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';
o.propertyIsEnumerable('prop')  // true
a.propertyIsEnumerable(0);  // true


Math.propertyIsEnumerable('random') // false
Object.propertyIsEnumerable('constructor') // false

从 用法1 和 用法2 可以看出用户自定义属性是可枚举的(一般情况下自定义属性都是可枚举的,除非像 person.sex 经过属性描述符的修改),而浏览器内置对象如 Math 的属性是不可枚举的。

3)原生构造函数的内置属性不可枚举,如Boolean, Number, String, Array, Date, Function, RegExp, Error, Object

var num = new Number();
for(var prop in num) {
    console.log(prop);
}

输出为空。for in 访问的是所有可枚举属性,这里输出为空,说明Number中内置的属性是不可枚举的,例如 toString() 方法。

4)自定义属性一般为可枚举属性( 不管是自身属性还是原始上的继承属性 )
说明:

  • 开发者自定义的属性在一般情况下是可枚举的
  • for /in 对所可以访问到所有可枚举属性
  • obj.propertyIsEnumerable(prop) 只能访问到 对象自身可枚举属性(对象自身添加的、构造函数实例化的) 有效,对原始上的继承属性无效。
  • obj.hasOwnProperty(prop) 返回一个布尔值,指示对象自身属性中是否具有指定的属性
  • Object.getOwnPropertyNames(obj) 返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
  • Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组。
//构造函数
function People() {
  this.hobby = 'eat';
}
People.prototype.showHooby = function() {};

//继承
function Coder() {
  this.love = function method() { return 'coder‘s love is codeing'; };
}
Coder.prototype = new People;
Coder.prototype.constructor = Coder;

//实例
var c = new Coder();
c.age = '24';
//打印出实例
console.dir(c)

我们来看看打印出来的实例对象,看看哪些属性是自身的,哪些属性是在原型上的


image.png

for/in 来访问 o 对象,看看哪些属性是可枚举的:

for(var prop in c){
    console.log(prop)
}
// love
// age
// hobby
// constructor
// showHooby 

自定义属性都可枚举,不管是自身属性还是原始上的继承属性

怎么过滤出自身可枚举属性呢?就可以用 obj.propertyIsEnumerable() , Object.getOwnPropertyNames(), obj.hasOwnProperty, Object.keys() 方法啦

// obj.propertyIsEnumerable()  --- 先找出*所有可枚举属性*,再找出自身的可枚举属性
for(var prop in c){
    if(c.propertyIsEnumerable(prop)) console.log(prop)
}
// love
// age


// 或者 obj.hasOwnProperty() --- 先找出*所有可枚举属性*,再找出自身属性
for(var prop in c){
    if(c.hasOwnProperty(prop)) console.log(prop)
}
// love
// age


// 或者 Object.getOwnPropertyNames() --- 先找出*所有自身属性*的属性名,再找出可枚举的
var cName = Object.getOwnPropertyNames(c);
for(var prop in cName){
    console.log(cName[prop])
}
// love
// age


// 或者 Object.keys() --- 直接找出自身可枚举属性
Object.keys(c) 
//["love", "age"]

参考链接:
MDN:Object
MDN: 属性的可枚举性和所有权

自己总结了大半天,然后看到阮大神比较全的一篇:
阮一峰:属性的可枚举与遍历

上面说到关于对象属性“枚举性”的多种方法,这里放放上一张这些属性微妙差别的对比图:


属性的可枚举性和所有权

相关文章

网友评论

    本文标题:JavaScript 中的枚举属性 enumeration

    本文链接:https://www.haomeiwen.com/subject/piswbxtx.html