먼저 for in 문을 사용하면 어떨까요
jqModal은 아마도 많은 사람들이 사용해 본 jquery 플러그인일 것입니다. jqModal 소스 코드 안에는 hs라는 함수가 있습니다. 중첩 루프는 다음과 같습니다.
for(var i in {jqmShow:1,jqmHide: 1})
for(var s in this[i])
if(H[this[i][s]])
H[this[i] [s]].w[i] (this);
return F;
}
순회에서 첫 번째 대상은 익명 객체입니다. 문제 없습니다.
두 번째 for in은 순회하여 컨텍스트에 따라 this[i]가 배열 객체(Array)인지 확인합니다.
많은 JS 선구자들이 배열 객체를 순회하기 위해 for in 문을 사용하지 말라고 경고했습니다. 성능 외에도 예상치 못한 버그가 발생할 수 있습니다. 조상의 말을 듣지 않으면 눈앞에서 그 결과를 겪게 될 것입니다.
오늘은 jqModal을 예로 들어 이런 종류의 버그가 언제 나타나는지 설명하고 이를 경고로 삼겠습니다.
두 번째, 문제가 다시 나타남
키워드: 기본 Array 클래스, 확장 Array 클래스
배열 객체를 순회하는 for in 문의 잠재적인 버그는 다음과 같습니다. 기본 Array 클래스가 다음과 같은 경우 js 스크립트 라이브러리가 프로토타입 확장된 경우(예: 추가 toJSON 메서드 추가, 즉 Array.prototype.toJSON=xxxx), 확장된 Array 객체를 순회하기 위해 for in을 사용하는 논리는 프로토타입 확장된 논리와 다릅니다. 네이티브 Array 객체를 순회하는 것입니다.
간단한 예로
var x=[1];
for(var s in x){
alert(s)
};
평소와 같이 Array는 기본 js 클래스, 위 명령문은 경고 메서드를 한 번만 실행해야 하며 s는 배열의 인덱스 0입니다. 그러나 Array 클래스가 추가 toJSON 메서드로 확장되면 위 문은 경고를 두 번 실행합니다. 첫 번째 s는 인덱스 0이고 두 번째 s는 메서드 이름 'toJSON'입니다.
당신이 디자인한 코드의 로직이 기본 Array 클래스를 기반으로 하고 어느 날 동료가 페이지에서 타사 JS 라이브러리를 참조하고 이 라이브러리가 우연히 Array 클래스를 확장하는 경우 결과는 다음과 같습니다. 원래 코드 논리가 더 이상 유지되지 않을 가능성이 매우 높다고 상상해 보십시오.
이러한 네이티브 JS 클래스를 확장하는 라이브러리 중 잘 알려진 것이 프로토타입.js인데, 이는 toJSON, Each 등 다양한 메서드를 Array 클래스로 확장합니다. 이제 나는 왜 jquery의 창시자가 프로토타입에 대해 그토록 화를 냈는지 이해합니다(많은 사람들이 특별한 이유로 같은 페이지에서 jquery와 프로토타입을 사용합니다. noCon충돌만으로는 해결할 수 없는 예상치 못한 충돌 문제가 많이 있을 것입니다.). 또한 jqModal의 작성자가 내 기사를 이해한다면 아마도 프로토타입에 대해 불평하면서 다음과 같이 말할 것입니다. "배열 순회에 for in을 사용하는 것은 현명하지 못하지만 더 나쁜 것은 프로토타입입니다..."
위에서 언급했듯이 jqModal을 사용하면서 동시에 다른 이유로 프로토타입을 사용하고 있다면 축하합니다. 속으신 것입니다. 충돌로 인해 jqModal의 팝업 상자는 ie6 및 ie7에서 closeClass에 의해 설정된 버튼을 사용하여 자동으로 닫힐 수 없습니다. 디버깅 코드를 추적하면 이 기사의 시작 부분에 언급된 hs 메서드의 for in 루프에 예외가 있음을 알 수 있습니다. . .
3. 문제 해결
배열 순회 시 for in 대신 for var 문을 사용하세요.