遍历对象属性

for (variable in object) { ... }

遍历对象本身的和从原型链上继承的可枚举的,非符号属性。(enumberable, non-Symbol)
Array、Object这样的从内置的构造函数创建的对象,会从Object.prototypeString.prototype继承不可枚举的属性(String,Number,Boolean,Object,Array,Function的原型属性是不可枚举的 ),比如String的indexOf方法或者Object的toString方法

const b = new Object()
for (let i in b) {console.log(i)}
// 什么也没有

ES6引入的新的原始数据类型Symbol,可以作为对象属性名,但是对象的Symbol属性也是不能通过for...in遍历得到

const obj = {};
const a = Symbol("a");
const b = Symbol.for("b");

obj[a] = "localSymbol";
obj[b] = "globalSymbol";

for (let i in obj) {console.log(i)}
// 也是什么也没有

// 对象的Symbol属性可以用`Object.getOwnPropertySymbols(obj)`获得
const objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(objectSymbols.length); // 2
console.log(objectSymbols)         // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0])      // Symbol(a)

通常和for in配合食用的方法:

obj.hasOwnProperty(prop)

判断对象属性中是否具有指定属性,返回布尔值。这个通常用来过滤对象从原型链上继承到的属性。
由于JavaScript 并没有保护 hasOwnProperty 属性名,比较靠谱的写法是下面这样(一些js linter设置里也有这一项)

Object.prototype.hasOwnProperty.call(obj, prop);  // 或者({}).hasOwnProperty.call

之前都没怎么在意,虽然在编辑器提示的督促下一直会写……今天加es5-shim兼容ie8,结果项目里有个什么js里面各种for in不判断原型继承,被坑的死死的_(:з」∠)_

for...of

for (variable of iterable) {...}

长得和for in有点像,只对可迭代对象创建迭代循环(ie好像不支持)
内置可迭代对象:String, Array, TypedArray, Map, Set
其他可迭代对象:arguments, DOM集合(如NodeList)

其他

Object.getOwnPropertyNames(obj)

返回一个对象自身(不包括从原型链继承到的)的可枚举和不可枚举的属性名组成的数组,但是这里不包括Symbol属性(ie9+)

Object.keys(obj)

返回对象自身可枚举属性组成的数组(ie9+)

Object.defineProperty(obj, prop, descriptor)

在对象上定义新属性,或修改现有属性,并返回该对象(ie9+)
用该方法定义的属性默认enumerable为false,即不可枚举;
相关的还有Object.defineProperties(obj, props)

Comments
Write a Comment