JavaScript가 객체를 반복하는 두 가지 방법을 제공한다는 것은 누구나 알고 있습니다.
1. for 루프
부적절:
루프될 때마다 배열의 길이를 얻어야 합니다.
종료 조건이 명확해야 합니다.
for 루프에서는 배열 또는 인수 및 HTMLCollection 객체와 같은 배열과 유사한 객체의 값을 반복할 수 있습니다. 일반적인 루프 형식은 다음과 같습니다.
// 次佳的循环 for (var i = 0; i < myarray.length; i++) { // 使用myarray[i]做点什么 }
이러한 형태의 루프의 단점은 루프를 수행할 때마다 배열의 길이를 얻어야 한다는 것입니다. 이렇게 하면 특히 myarray가 배열이 아니고 HTMLCollection 객체인 경우 코드 성능이 저하됩니다.
HTMLCollections는 DOM 메서드에서 반환된 개체를 참조합니다. 예:
document.getElementsByName()
document.getElementsByClassName()
document.getElementsByTagName()
DOM 표준 이전에 도입되어 오늘날에도 여전히 사용되고 있는 다른 HTMLCollection이 있습니다. 예:
document.images: 페이지의 모든 이미지 요소
document.links: 모든 태그 요소
document.forms : 모든 양식
document.forms[0].elements : 페이지의 첫 번째 양식에 있는 모든 필드
컬렉션의 문제점은 기본 문서(HTML 페이지)를 실시간으로 쿼리한다는 것입니다. 즉, 컬렉션의 길이에 액세스할 때마다 실시간으로 DOM을 쿼리해야 하며 DOM 작업은 일반적으로 비용이 많이 듭니다.
다음 코드와 같이 값을 반복할 때 배열(또는 컬렉션)의 길이를 캐시하는 것이 좋은 이유는 다음과 같습니다.
for (var i = 0, max = myarray.length; i < max; i++) { // 使用myarray[i]做点什么 }
이런 방식으로 이 루프 중에 길이 값을 한 번만 검색할 수 있습니다.
콘텐츠 검색을 위해 반복할 때 HTMLCollection의 캐시 길이는 모든 브라우저에서 2배(Safari3)에서 190배(IE7) 사이로 더 빠릅니다. //이 데이터는 매우 오래된 것으로 보입니다
루프에서 컬렉션을 명시적으로 수정하려는 경우(예: DOM 요소 추가) 상수보다는 길이 업데이트를 선호할 수 있습니다.
단일 var 형식을 사용하면 다음과 같이 루프에서 변수를 꺼낼 수 있습니다.
function looper() { var i = 0, max, myarray = []; // ... for (i = 0, max = myarray.length; i < max; i++) { // 使用myarray[i]做点什么 } }
이 형식은 단일 var 형식을 고수하므로 일관성이라는 이점이 있습니다. 단점은 코드를 리팩토링할 때 전체 루프를 복사하여 붙여넣는 것이 약간 어렵다는 것입니다. 예를 들어, 한 함수에서 다른 함수로 루프를 복사하는 경우 i와 max를 새 함수에 도입할 수 있는지 확인해야 합니다(여기서 유용하지 않으면 원래 함수에서 삭제해야 할 가능성이 높습니다). ) 잃다).
루프의 마지막 조정은 i를 아래 표현식 중 하나로 바꾸는 것입니다.
i = i + 1 i += 1
JSLint는 "과도한 까다로움"을 촉진하기 때문에 이 작업을 수행하도록 요청합니다. 이를 무시하면 JSLint의 plusplus 옵션은 false가 됩니다(기본값은 기본값임).
두 가지 변형:
//第一种变化的形式: var i, myarray = []; for (i = myarray.length; i–-;) { // 使用myarray[i]做点什么 } //第二种使用while循环: var myarray = [], i = myarray.length; while (i–-) { // 使用myarray[i]做点什么 }
이러한 작은 개선 사항은 성능만을 위한 것이며 JSLint는 i-- 사용에 대해 불만을 표시합니다.
2. for…in 루프 - "열거형"이라고도 함
for…in 루프는 객체의 속성이나 배열의 각 요소를 반복하는 데 자주 사용됩니다. for…in 루프의 루프 카운터는 숫자가 아니라 문자열입니다. 여기에는 현재 속성의 이름이나 현재 배열 요소의 인덱스가 포함됩니다. 다음은 몇 가지 예입니다.
객체를 순회할 때 루프 카운터인 변수 i는 객체의 속성 이름입니다.
//使用for..in循环遍历对象属性 varperson={ name: "Admin", age: 21, address:"shandong" }; for(var i in person){ console.log(i); }
실행 결과는 다음과 같습니다.
이름
나이
주소
배열을 순회할 때 루프 카운터인 변수 i는 현재 배열 요소의 인덱스입니다.
//使用for..in循环遍历数组 vararray = ["admin","manager","db"] for(vari in array){ console.log(i); }
실행 결과:
0
1
2
그러나 이제는 for..in 루프가 사용하기 매우 쉬운 것 같습니다. 하지만 너무 성급하게 생각하지 마세요. 다음 예를 살펴보세요.
var array =["admin","manager","db"]; //给Array的原型添加一个name属性 Array.prototype.name= "zhangsan"; for(var i in array){ alert(array[i]); }
运行结果:
admin
manager
db
zhangsan
咦,奇观了,怎么平白无故的冒出来一个zhangsan
现在,再看看使用 for循环会怎样?
vararray = ["admin","manager","db"]; //给Array的原型添加一个name属性 Array.prototype.name = "zhangsan"; for(var i =0 ; i<array.length; i++){ alert(array[i]); };
运行结果:
admin
manager
db
哦, 现在明白了,for..in循环会把某个类型的原型(prototype)中方法与属性给遍历出来,所以这可能会导致代码中出现意外的错误。为了避免这个问题,我们可以使用对象的hasOwnProperty()方法来避免这个问题,如果对象的属性或方法是非继承的,那么hasOwnProperty() 方法返回true。即这里的检查不涉及从其他对象继承的属性和方法,只会检查在特定对象自身中直接创建的属性。
vararray = ["admin","manager","db"]; Array.prototype.name= "zhangshan"; for(var i in array){ //如果不是该对象自身直接创建的属性(也就是该属//性是原型中的属性),则跳过显示 if(array.hasOwnProperty(i)){ alert(array[i]); } }
运行结果:
admin
manager
db
另外一种使用hasOwnProperty()的形式是取消Object.prototype上的方法。像这样:
// 对象 var man = { hands: 2, legs: 2, heads: 1 }; for (var i in man) { if (Object.prototype.hasOwnProperty.call(man, i)) { // 过滤 console.log(i, ":", man[i]); } }
其好处在于在man对象重新定义hasOwnProperty情况下避免命名冲突。也避免了长属性查找对象的所有方法,你可以使用局部变量“缓存”它。
var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) { if (hasOwn.call(man, i)) { // 过滤 console.log(i, ":", man[i]); } }
严格来说,不使用hasOwnProperty()并不是一个错误。根据任务以及你对代码的自信程度,你可以跳过它以提高些许的循环速度。但是当你对当前对象内容(和其原型链)不确定的时候,添加hasOwnProperty()更加保险些。
格式化的变化(通不过JSLint)会直接忽略掉花括号,把if语句放到同一行上。其优点在于循环语句读起来就像一个完整的想法(每个元素都有一个自己的属性”X”,使用”X”干点什么):
// 警告: 通不过JSLint检测 var i, hasOwn = Object.prototype.hasOwnProperty; for (i in man) if (hasOwn.call(man, i)) { // 过滤 console.log(i, ":", man[i]); }
以上就是介绍了JavaScript提供的两种方式迭代对象:for循环和for...in循环,希望这篇文章对大家的学习有所帮助。