for…in语句和in运算符

今天在用for in 循环遍历的时候,出现了部分不符合我以为的预期的行为,于是了解了一下for in 的行为。后来突发奇想,js 里还有in 运算符可以来判断一个对象是否有某个属性,比较好奇,for in里的in和运算符in表现是否一致?

for…in

for...in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性。(包括它的原型链上的可枚举属性)。属性定义

for (variable in object)
  statement

来个例子:

var obj=Object.create({a:1}) //prototype ,打印
obj.b=2  // 打印
obj.c=undefined // 打印
obj.d=3
delete obj.d // 不打印
obj[Symbol('e')]=4 //不打印
Object.defineProperty(obj, 'f', {enumerable:false}) //不打印,不可枚举
for (var prop in obj) {
  console.log("obj." + prop + " = " + obj[prop]);
}

// Output:
// obj.b = 2
// obj.c = undefined
// obj.a = 1

我们可以看到,打印出了b、c、a ,并不是按照我们定义的顺序打印的。

总结一下:

  1. 遍历顺序不确定
  2. 包括原型链上的属性
  3. 忽略key为symbol 的属性
  4. 忽略key不可枚举 的属性
  5. 不忽略属性值为undefined 的key
  6. 已经delete 的属性不会再有

in运算符

如果指定的属性在指定的对象或其原型链中,则in 运算符返回true

来个例子:

var obj=Object.create({a:1}) //prototype ,打印
obj.b=2  // 打印
obj.c=undefined // 打印
obj.d=3
delete obj.d // 不打印
var e=Symbol('e')
obj[e]=4 //不打印
Object.defineProperty(obj, 'f', {enumerable:false}) //不打印,不可枚举

'a' in obj // true
'b' in obj // true
'c' in obj // true
'd' in obj // false
 e in obj // true
'f' in obj // true

总结一下:

  1. 可以判断原型链上的属性
  2. 可以判断值为undefined 的属性
  3. 可以判断自身的属性
  4. 可以判断key 为symbol 的属性
  5. 可以判读不可枚举的属性
  6. 被删除的属性视为不存在(理应如此)

可以看到,in运算符还是非常的具有实用价值,再也不用Object.keys(obj).includes(k)来判断了。但要注意`!` 运算符的优先级比`in`高。

if(!('a' in obj)){
	//括号不能漏
}

总结

for in语句中的in和运算符in关系不大,并且表现不完全一致。in运算符基本上可以检测一个对象上是否拥有某个属性,而for in在遍历的时候,会忽略symbol类型的key 和不可枚举的key。

值得一提的是,for in遍历会把原型链上的属性也遍历出来,而与之对应的,我们经常用来获取对象的所有key 的Object.keys()函数,只会取出属于对象本身的属性值,不知道这个区别你有注意到吗?

Leave a Comment

邮箱地址不会被公开。 必填项已用*标注