Javascript Cookbook

연관 배열을 사용해서 폼 요소의 이름과 값 저장하기

문제

이후에 유효성 검증을 하기 위해 폼 요소의 이름과 값을 저장하고 싶다.

해결

연관 배열을 사용하고 요소 이름을 배열 인덱스로 사용하면 요소를 저장할 수 있다.

var elemArray = new Object();   //Array가 아닌 Object임에 주의
var elem = document.forms[0].elements[0];
elemArray[elem.id] = elem.value;

for...in 문을 사용해서 배열을 탐색한다.

for(var key in elemArray){
    str+=key + "," + elemArray[key] + " ";
}

설명

자바스크립트에서는 배열 인덱스가 키워드를 나타내는 문자열이고, 이 문자열에 주어진 값을 매핑하는 연관 배열을 만들 수 있다. 해결에서 배열 인덱스는 주어진 배열 원소의 식별자이고, 배열의 실제 값은 폼 요소의 값이다.

연관 배열을 만들 수 있지만 이를 위해 Array 객체를 사용하지는 않는다. Array 객체를 사용하는 것은 위험하고 사실상 추천하지 않는다. Array.prototype을 통해 Array 객체의 기능을 확장하면 Array 객체를 사용해서 작성된 연관 배열을 for...in 반복문에서 사용할 때 문제가 발생한다.

for...in 반복문은 String 객체의 속성이나 개발자가 직접 작성한 객체의 속성과 같은 어떤 객체의 속성에 대해 반복하는 것이다.

Array 객체를 연관 배열로 만들어 사용할 때 실제로 원하는 것은 배열 원소를 추가하는 것이 아니라 배열 객체에 속성을 추가하는 것이다. Array 뿐만 아니라 RegExp 또는 String으로도 연관 배열을 만들 수 있다. 자바스크립트에서 이런 일이 가능한 이유는 객체가 연관 배열로 되어 있기 때문이다.

배열에 새 값을 추가할 때

obj[propName] = "somevalue";

이때 실제로는 객체에 새로운 속성이 추가된 것이다.

obj.propName = "somevalue";

연관 배열이 숫자 기반 배열과 어떻게 다른지 더 알아보자. Array를 사용해서 연관 배열을 작성하면 인덱스 배열의 '원소'에 접근할 수 없고 length 속성은 0을 반환한다.

Array 대신 자바스크립트의 Object를 직접 사용해서 연관 배열을 작성하면 똑같은 기능을 하면서도 prototype을 사용해서 Array 객체를 확장한 라이브러리와의 충돌을 피할 수 있다.

다음 예제는 폼이 전송될 때 type속성이 text인 모든 요소에 접근해서 이를 연관 배열에 저장한다.

<!DOCTYPE html>
<html>
  <head>
    <title>연관 배열</title>
    <script>
      //폼 요소의 이름과 값 구하기
      function getVals(){
        var elems = document.getElementById("picker").elements;
        var elemArray = new Object();
        for(var i=0;i<elems.length;i++){
          if(elems[i].type == "text")
            elemArray[elems[i].id] = elems[i].value;
        }
        checkVals(elemArray);
        return false;
      }

      //값 확인
      function checkVals(elemArray){
        var str = "";
        for(var key in elemArray){
          str+=key+","+elemArray[key]+" ";  
        }
        document.getElementById("result").innerHTML = str;
      }
    </script>
  </head>

  <body>
    <form id="picker" onsubmit="return getVals()">
      <label>값 1:</label> <input type="text" id="first" /><br />
      <label>값 2:</label> <input type="text" id="second" /><br />
      <label>값 3:</label> <input type="text" id="third" /><br />
      <label>값 4:</label> <input type="text" id="four" /><br />
      <input type="submit" value="유효성 검사" />
    </form>
    <div id="result"></div>
  </body>
</html>

예제보기 http://embed.plnkr.co/zRoiLIssGBfAGUGoq0E2/preview

이 예제에서 배열 인덱스로 폼 요소의 아이디를 사용했다는 것을 기억해야 한다. 배열을 탐색할 때 for 반복문을 아래와 같이 사용할 수 있다.

for(keyword in array)

이 문법은 배열 인덱스에 접근한다. 배열 인덱스는 keyword 변수에 할당되어 배열값에 접근할 때 사용할 수 있다.

for(keyword in array)
    var a = array[keyword];

자바스크립트에는 진짜 해시맵 기능이 없지만 이런 형태의 **키워드/값 쌍을 일반적으로 해시맵(hash map) 또는 해시 테이블(hash table)이라고 부른다. 자바스크립트의 해시 맵을 진짜 해시 맵이라 부르지 않는 이유는 같은 키워드에 여러 값을 사용할 수 없고 키워드로 문자열만 사용할 수 있기 때문이다.