for in문에서 이해할수 없는 현상이 일어납니다

조회수 2239회

간단한 form 유효성 검사를 하고 있습니다. 대단한건 아니고 값이 입력되기만 하면 submit 버튼을 활성화시키는 건데요 submit은 기본적으로 disabled해놓고 form값이 바뀔때마다 유효성검사를 돌립니다. 검사할 HTML form은 input text와 textarea고요, textarea개수가 변화할 수 있어서 매번 체크합니다.

$('.mainBlock').on('change', function(){
    var arr = $('.mainBlock input[type], .mainBlock textarea');
    for(i in arr){
            console.log(arr[i].value);
        if(arr[i].value){
            $('.mainBlock button[type="submit"]').removeAttr('disabled');
            console.log(arr[i]);
            console.log('remove');
        }else{
            $('.mainBlock button[type="submit"]').attr('disabled', 'disabled');
            console.log(arr[i]);
            console.log('attr');
            break;
        }
    }
});

일단 문제점은 text와 textarea가 다 채워져도 attr('disabled', 'disabled')가 계속해서 실행된다는 것이고요, 진행상황을 확인하기 위해 console.log를 넣었는데

//csrf 코드
<input type="hidden" name="_csrf" value="~~">    //csrf node
remove    //확인용
test    //input text value
<input type="text" maxlength="30" class="form-control">    //input text node
remove    //확인용
test1    //textarea value
<textarea maxlength="300" class="form-control">    //textarea node
remove    //확인용
a1    //input text value
<input type="text"class="form-control">    //input text node
remove    //확인용
undefined
4
attr

저 마지막 세줄이 문제입니다. object length가 나오는 이유도 모르겠고 왜 자꾸 attr이 실행되는지 모르겠습니다.

3 답변

  • 좋아요

    6

    싫어요
    채택 취소하기

    @장성원 님 답변처럼 for in은 속성을 돌게 됩니다.

    for(i in arr)
    

    코드에서 i를 배열의 index가 들어갈거라고 예상하신듯 한데 그렇게 하려면

    for(var i = 0 ; i < arr.length ; i++)
    

    문법을 사용하셔야 합니다.

    크롬에서 for in 문을 사용하게 되면 이미지 이름이나 설명을 여기에 넣어주세요.

    이렇게 프로퍼티들이 나열되게 되죠..

    for in은 브라우저별로 처리가 다르다고 하니.. 일반적일 loop에서는 그냥 for 문을 쓰시길 권해드립니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • for in과 for문이 또 그런 차이점이 있었군요.. Snark 2016.3.28 22:23
  • 감으로 답변을 다는것이긴한데

    아래와 같이 each로 순환하셔야합니다. 기본적으로 javascript 에서 for in 은 배열일경우 돌기는 하지만 특정속성 프로퍼티를 돌기위해만들어진 속성입니다. 따라서 배열을 돌기위해선 for문이나 아니면 each를통해서 순환하는것이 맞습니다.

    
    var arr = $('.mainBlock input[type], .mainBlock textarea');
    
    arr.each(function(){
        console.log(this.value);
        if(this.value){
            $('.mainBlock button[type="submit"]').removeAttr('disabled');
            console.log(this);
            console.log('remove');
        }else{
            $('.mainBlock button[type="submit"]').attr('disabled', 'disabled');
            console.log(this);
            console.log('attr');
            break;
        }   
    });
    
    
    • (•́ ✖ •̀)
      알 수 없는 사용자
    • (•́ ✖ •̀)
      알 수 없는 사용자
    • each 내에서 break;는 쓰지 못합니다. 알 수 없는 사용자 2016.3.28 18:41
    • 감사합니다! 큰 도움이 되었습니다 Snark 2016.3.28 22:10
  • 질문 주신 부분은 언어의 기반을 구성하고 있는 부분이기 때문에 동작 원리를 정확하게 짚고 넘어가셔야 합니다.

    자바스크립트는 프로토타입 방식의 객체 모델을 사용하는 언어입니다. 이런 방식을 사용하는 다른 언어로는 self, io등이 있습니다.

    이러한 프로토타입 기반 언어들은 자신에게 없는 속성을 부모 객체에 물어보는 특징이 있습니다.

    그리고 for in 구문 자신이 가진 모든 속성을 나열해 줍니다. 문제는 for in 구문이 자신이 가진 속성 외에도 부모의 속성도 함께 나열한다는데 있습니다.

    var arr = $('.mainBlock input[type], .mainBlock textarea');
    

    위의 경우 arr은 순수한 자바스크립트 객체가 아니라, jQuery객체입니다. 따라서 jQuery가 가지고 있는 별도 속성이 함께 나열되는 것입니다.

    이를 피하기 위해서는 다른 분들이 설명해 주신 것과 같이 전통적인 C 스타일의 index를 사용하는 for문을 사용하시거나 jQuery에서 제공하는 each함수를 사용하시면 방법이 있습니다.

    여기서 위의 each함수는 jQuery의 구현이기 때문에 자바스크립트 코어에서 제공되는 forEach함수와는 동작이 조금 다릅니다.

    이점 유의해서 사용하시면 될 것 같습니다.

    참고: hasOwnProperty

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 기초이론이 좀 부족한것 같네요.. 더 정진해야겠습니다 Snark 2016.3.28 22:11
    • @snark 기초라고 적은게 좀 어감이 안좋네요. 기초 -> 기반 으로 정정하겠습니다 :) 알 수 없는 사용자 2016.3.28 22:43
    • 오오~!! 많이 배우고 갑니다.(__)* 알 수 없는 사용자 2016.3.29 11:06

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)