pfan123/Articles

JavaScript 中 for in 循环和数组的问题

pfan123 opened this issue · 0 comments

for...in 语句以任意顺序遍历一个对象的可枚举(enumerable)属性。对于每个不同的属性,语句都会被执行。

for...in 遍历对象:

let tMinus = {
    two: "Two",
    one: "One",
    zero: "zero"
};
 
let countdown = "";
 
for (let step in tMinus) {
    countdown += tMinus[step] + " ";
}
 
console.log(countdown);  // Two  One  zero

因为for…in循环支持所有的JavaScript对象,所以它同样可用于数组对象之中:

let tMinus = [
    "Two",
    "One",
    "zero"
];
 
let countdown = "";
 
for (let step in tMinus) {
    countdown += tMinus[step] + " ";
}
 
console.log(countdown);   // Two  One  zero

然而,以这样的方式遍历数组存在部分问题。

为内置原型添加属性/方法,for in时也是可遍历

Array.prototype.voice = "voice";
 
let tMinus = [
    "Two",
    "One",
    "zero"
];
 
let countdown = "";
 
for (let step in tMinus) {
    countdown += tMinus[step] + " ";
}
 
console.log(countdown);  // Two  One  zero  voice

可借助getOwnPropertyNames() 或执行 hasOwnProperty() 函数来避免这一问题

Array.prototype.voice = "voice";
 
let tMinus = [
    "Two",
    "One",
    "zero"
];
 
let countdown = "";
 
for (let step in tMinus) {
	if( tMinus.hasOwnProperty(step) ){
		countdown += tMinus[step] + " ";
	}
}
console.log(countdown);  // Two  One  zero 

迭代的顺序是依赖于执行环境的,数组遍历不一定按次序访问元素

可能出现这样的结果

console.log(countdown);  //One  zero  Two

向数组变量添加额外的属性,会导致不可预知的结果

let tMinus = [
    "Two",
    "One",
    "zero"
];
 
tMinus.vioce = "vioce";
 
let countdown = "";
 
for (let step in tMinus) {
    if (tMinus.hasOwnProperty(step)) {
        countdown += tMinus[step] + " ";
    }
}
 
console.log(countdown);  // Two  One  zero  vioce

由此可见,当你需要遍历数组元素的时候,应使用for循环或者数组对象的内置迭代函数(如forEach、map等),而不是for…in循环。

javascript检测对象中是否存在某个属性

检测对象中属性的存在与否可以通过几种方法来判断。

1.使用in关键字

该方法可以判断对象的自有属性和继承来的属性是否存在。

let obj = { x: 1 }
"x" in obj;            //true,自有属性存在
"y" in obj;            //false
"toString" in obj;     //true,是一个继承属性

2.使用hasOwnProperty()方法

该方法只能判断自有属性是否存在,对于继承属性会返回false。

let obj = { x: 1 }

obj.hasOwnProperty("x")   //true,自有属性中有x
obj.hasOwnProperty("y")	  //false,自有属性中不存在y
obj.hasOwnProperty("toString")   //false,这是一个继承属性,但不是自有属性