내 JavaScript 파일에서 JSLint 를 사용했습니다 . 오류가 발생했습니다.
for( ind in evtListeners ) {
41 행의 문제 문자 9 : for의 본문은 if 문에 싸서 프로토 타입에서 원하지 않는 속성을 필터링해야합니다.
이것은 무엇을 의미 하는가?
내 JavaScript 파일에서 JSLint 를 사용했습니다 . 오류가 발생했습니다.
for( ind in evtListeners ) {
41 행의 문제 문자 9 : for의 본문은 if 문에 싸서 프로토 타입에서 원하지 않는 속성을 필터링해야합니다.
이것은 무엇을 의미 하는가?
답변:
우선 , 루프를 사용 하여 배열을 열거 하지 마십시오for in
. 못. 좋은 오래된 것을 사용하십시오 for(var i = 0; i<arr.length; i++)
.
그 이유는 다음과 같습니다. JavaScript의 각 객체에는이라는 특수 필드가 prototype
있습니다. 해당 필드에 추가 한 모든 항목은 해당 유형의 모든 개체에서 액세스 할 수 있습니다. 모든 배열에 filter_0
0을 걸러내는 멋진 새 함수를 갖기를 원한다고 가정하십시오 .
Array.prototype.filter_0 = function() {
var res = [];
for (var i = 0; i < this.length; i++) {
if (this[i] != 0) {
res.push(this[i]);
}
}
return res;
};
console.log([0, 5, 0, 3, 0, 1, 0].filter_0());
//prints [5,3,1]
이것은 객체를 확장하고 새로운 메소드를 추가하는 표준 방법입니다. 많은 라이브러리가이를 수행합니다. 그러나 for in
지금 어떻게 작동 하는지 봅시다 :
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
당신이 보여요? filter_0이 또 다른 배열 인덱스라고 생각합니다. 물론 실제로는 숫자 인덱스가 아니라 숫자 인덱스뿐만 아니라 for in
개체 필드를 통해 열거됩니다. 이제 모든 숫자 인덱스 와를 통해 열거 하고filter_0
있습니다. 그러나 filter_0
특정 배열 객체의 필드는 아니며 모든 배열 객체에는이 속성이 있습니다.
운 좋게도 모든 객체에는 hasOwnProperty
이 필드가 실제로 객체 자체에 속하는지 또는 단순히 프로토 타입 체인에서 상속되어 해당 유형의 모든 객체에 속하는지 확인 하는 메소드가 있습니다.
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
참고,이 코드는 작동하지만 배열에 대한 예상대로, 당신이해야 결코, 결코 , 사용 for in
및 for each in
배열. for in
배열 인덱스 나 값이 아니라 객체의 필드 를 열거합니다.
var listeners = ["a", "b", "c"];
listeners.happy = "Happy debugging";
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
// happy
for in
언어는 for in
배열을 열거 하는 순서를 지키지 않기 때문에 배열을 반복 하는 데 사용 해서는 안됩니다 . 숫자 순서가 아닐 수 있습니다. 또한`for (i = 0; i <array.length; i ++) 스타일 구문을 사용하면 숫자 인덱스 만 순서대로 반복하고 영숫자 속성 은 없는지 확인할 수 있습니다 .
for-in
루프 에서 멀어지게 만드는 대신 (정말 훌륭하지만) 어떻게 작동하는지 교육하고 (이 답변에서 올바르게 수행됨) 소개하여 Object.defineProperty()
프로토 타입을 안전하게 확장하지 않고도 프로토 타입을 안전하게 확장해야한다고 생각합니다. 또한 기본 개체의 프로토 타입을 확장 하지 않고 확장하면 안됩니다Object.defineProperty
.
jslint의 저자 인 Douglas Crockford는이 문제에 대해 여러 번 글을 썼습니다. 그의 웹 사이트 의이 페이지에는 이것을 다루는 섹션 이 있습니다 :
성명서
문장 클래스의 형식은 다음과 같아야합니다.
for (initialization; condition; update) { statements } for (variable in object) { if (filter) { statements } }
첫 번째 형식은 배열과 미리 결정 가능한 반복 횟수의 루프와 함께 사용해야합니다.
두 번째 양식은 객체와 함께 사용해야합니다. 객체의 프로토 타입에 추가 된 멤버는 열거에 포함됩니다. hasOwnProperty 메소드를 사용하여 객체의 실제 멤버를 구별하여 방어 적으로 프로그래밍하는 것이 좋습니다.
for (variable in object) { if (object.hasOwnProperty(variable)) { statements } }
Crockford는 또한 YUI 극장에서 이에 대해 이야기하는 비디오 시리즈를 가지고 있습니다. 자바 스크립트에 대한 Crockford의 일련의 비디오 / 토크는 자바 스크립트에 대해 약간 진지한 지 반드시 확인해야합니다.
바바의 대답은 표에있다. jQuery를 사용하면 $.each()
함수가이를 처리하므로 사용하는 것이 더 안전합니다.
$.each(evtListeners, function(index, elem) {
// your code
});
$.each
(또는 underscore.js 's _.each
)를 사용하지 않는 것이 좋습니다 for
. jsperf에는 실행 가치 가 있는 몇 가지 눈에 띄는 비교 테스트 가 있습니다.
@all-JavaScript의 모든 것은 객체 ()이므로 "객체에서만 사용"과 같은 문장은 약간 오해의 소지가 있습니다. 또한 JavaScript는 강력하게 입력되지 않으므로 1 == "1"은 true입니다 (1 === "1"은 아니지만 Crockford는이 값이 큽니다). JS에서 배열의 progromatic 개념에 관해서는, 정의에서 타이핑이 중요합니다.
@Brenton-용어 독재자가 될 필요는 없습니다. "연관 배열", "사전", "해시", "개체", 이러한 프로그래밍 개념은 모두 JS에서 하나의 구조에 적용됩니다. 이름 (키, 인덱스) 값 쌍입니다. 여기서 값은 다른 객체 일 수 있습니다 (문자열도 객체 임)
그래서,
new Array()
과 동일[]
new Object()
대략 비슷하다 {}
var myarray = [];
모든 인덱스 (일명 키)가 정수 여야한다는 제한이있는 배열 인 구조체를 만듭니다. 또한 .push ()를 통해 새 인덱스를 자동 할당 할 수 있습니다
var myarray = ["one","two","three"];
실제로 비아를 다루는 것이 가장 좋습니다 for(initialization;condition;update){
그러나 어떻습니까 :
var myarray = [];
myarray[100] = "foo";
myarray.push("bar");
이 시도:
var myarray = [], i;
myarray[100] = "foo";
myarray.push("bar");
myarray[150] = "baz";
myarray.push("qux");
alert(myarray.length);
for(i in myarray){
if(myarray.hasOwnProperty(i)){
alert(i+" : "+myarray[i]);
}
}
아마도 배열을 가장 잘 사용하지는 않지만 항상 명확한 것은 아닙니다.
키를 알고 있고 정수가 아닌 경우 구조 옵션과 같은 유일한 배열 옵션은 객체입니다.
var i, myarray= {
"first":"john",
"last":"doe",
100:"foo",
150:"baz"
};
for(i in myarray){
if(myarray.hasOwnProperty(i)){
alert(i+" : "+myarray[i]);
}
}
확실히 말하기에는 약간 극단적입니다
... for 루프를 사용하여 배열을 열거하지 마십시오. 못. 에 대한 오래된 것을 사용하십시오 (var i = 0; i <arr.length; i ++)
?
Douglas Crockford 추출물의 섹션을 강조 할 가치가 있습니다.
... 두 번째 형태는 객체와 함께 사용해야합니다 ...
숫자가 아닌 키 대신 이름이 지정된 연관 배열 (일명 hashtable / dictionary)이 필요한 경우이를 객체로 구현해야합니다 (예 :) var myAssocArray = {key1: "value1", key2: "value2"...};
.
이 경우 myAssocArray.length
(이 객체에는 '길이'속성이 없기 때문에) null이 i < myAssocArray.length
되며 멀리 가지 않습니다. 배열 키는 유용한 속성 (예 : 배열 멤버의 ID 속성 또는 이름)이 될 수 있기 때문에 더 큰 편의성을 제공하는 것 외에도, 연관 배열은 많은 상황에서 성능 이점을 제공 할 것으로 예상됩니다. 배열을 반복해서 평가하여 원하는 배열 항목을 찾습니다.
어쨌든 JSLint 오류 메시지에 대한 설명 덕분에 무수한 연관 배열을 통해 간섭 할 때 'isOwnProperty'확인을 사용합니다!
length
속성이 없지만 다른 방법으로 수행 할 수 있습니다.var myArr = []; myArr['key1'] = 'hello'; myArr['key2'] = 'world';
var myArr = []
않아야합니다 var myArr = {}
.PHP에서는 동일한 것이지만 JS는 아닙니다.
이는 hasOwnProperty 메소드를 사용하여 evtListeners의 특성을 필터링해야 함을 의미합니다 .
in / for / $. each에 대한 주제를 추가하기 위해 $ .each vs. for http://jsperf.com/each-vs-for-in/2에 대한 jsperf 테스트 사례를 추가했습니다.
다른 브라우저 / 버전은 다르게 처리하지만 성능이 가장 저렴한 옵션은 $ .each 및 똑바로 나타납니다.
연관 배열 / 객체를 반복하고, 이후의 것을 알고 다른 모든 것을 무시하는 데 사용하는 경우 jQuery를 사용하거나 jQuery를 사용하거나 중단 한 경우 $ .each를 사용하십시오. 당신이 마지막 요소가되어야한다는 것을 알게되었습니다.)
배열을 통해 각 키 쌍으로 무언가를 수행하는 경우 jQuery를 사용하지 않으면 hasOwnProperty 메소드를 사용하고 jQuery를 사용하는 경우 $ .each를 사용해야합니다.
for(i=0;i<o.length;i++)
하지만 연관 배열이 필요하지 않은 경우 항상 사용 하십시오. lol chrome은 for 또는$.each
if (evtListeners.hasOwnProperty(ind))
처리되어 소유 (비상 속) 속성 만 처리하도록 제한됩니다. 여전히 어떤 경우에는 상속 된 속성을 포함하여 모든 속성을 반복하려고합니다. 이 경우 JSLint는 if 문에 루프 본문을 감싸서 실제로 원하는 속성을 결정하도록합니다. 이것은 작동하고 JSlint를 행복하게 할 것입니다 :if (evtListeners[ind] !== undefined)