我爱编程

JS - 面向对象 - 属性遍历

2018-08-04  本文已影响32人  Iceesong

对象属性分类

对于属性遍历而言,可以将对象属性分为是否可枚举、是否为继承 两种

let ary = ['a', 'b', 'c']

ary 数组中,可枚举属性是对应的索引 0, 1, 2 ,不可枚举的是 length

对象属性配置

对象中,属性是否可枚举可以通过 Object.defineProperty 设定

class Car {                                          // 创建类
  constructor(brand, model, color) {                
    this.brand = brand
    this.model = model
    this.color = color
  }
}

let mycar = new  Car('Tesla', 'model 3', 'red')     // 没有的话 new 一个就好啦

Object.defineProperty(mycar ,"color",{
        value: "red",
        enumerable: false,       //是否可枚举, 默认值 false
        configurable: false,    //是否可配置,默认值 false
        writable: false,        //没有 writable 使用默认值 false
  });

对象创建完成,在控制台内通过颜色可以判断不可枚举属性,但作为一个严谨的程序员,当然需要更科学的办法啦

可枚举属性

Object.keys(o)

按顺序遍历返回一个数组,其包含对象 o 自身(不包括原型)的所有可枚举属性的名称

Object.keys(mycar)          
// ["brand", "model"] 
for...in循环

该方法会依次访问一个对象及其原型链中所有可枚举的属性,就当前对象而言,效果较Object.keys(o) 相同

for (let i in my car) {
  console.log(i)
}
// brand
// model

但如果继承的原型链上已有可枚举属性,原型上的 'foo' 也被遍历进来了

mycar.__proto__.foo = 'foo'

for (let i in mycar) {
  console.log(i)
}
// brand
// model
// foo

Object.keys(mycar)          
// ["brand", "model"] 

所以得再过滤下,使用 hasOwnProperty 过滤继承属性,返回布尔值

for(let i in mycar){
  // 此处可以使用 mycar.hasOwnProperty(i),
  // 以安全的角度看用 Object.prototype.hasOwnProperty.call(mycar,i) 
  if(Object.prototype.hasOwnProperty.call(mycar,i)){
    console.log(i)
  }
}
// brand
// model

所有属性

Object.getOwnPropertyNames(o)

该方法返回一个数组,其包含对象 o 所有自有的属性(无论是否可枚举)的名称

mycar.__proto__.foo = 'foo'

Object.getOwnPropertyNames( mycar )
// ["brand", "model", "color"]

不可枚举属性

那既然可枚举和全部自有属性都有办法获取,要获取不可枚举属性就简单了

mycar.__proto__.foo = 'foo'

Object.getOwnPropertyNames(mycar).filter(val =>
  !Object.keys(mycar).includes(val)
)
// ["color"]

遍历顺序

值得注意的是,Object.keys() 遍历顺序对不同属性类型时,先后顺序不同

let a = {'zz': 3, 3: 99, 1: 100, 'bb': 0}        
//["1", "3", "zz", "bb"]

引用 MDN 中说明:

一个对象的属性名可以是任何有效的 JavaScript 字符串,或者可以被转换为字符串的任何类型,包括空字符串

也就是说,对象的所有属性都会通过转换变化为字符串,而由数字转过来字符串排序优先(此处略有疑问)而 for...in循环 遍历顺序与 Object.keys() 一致

// 同时创建多个变量
let myObj = new Object(),
str = "myString",
rand = Math.random(),
obj = new Object(),
num1 = 23,
num2 = 99,
ary = [1,2];

myObj.type              = "Dot syntax";
myObj["date created"]   = "String with space";
myObj[str]              = "String value";
myObj[rand]             = "Random Number";
myObj[obj]              = "Object";
myObj[ary]              = 'here is a ary'
myObj[num2]             = 'here is a number_2'
myObj[""]               = "Even an empty string";
myObj[num1]             = 'here is a number_1'

for(let i in myObj){console.log(typeof i,' --- ', i, ' --- ',myObj[i])}
// 去下图...

小结

统计表

源自 MDN ,关于属性的 枚举,继承 统计表

上一篇下一篇

猜你喜欢

热点阅读