본문 바로가기
프로그래밍/jQuery

jQuery API 정복 - 결과를 배열로 돌려받기, map()

by zoo10 2011. 6. 8.

.map()

원문 링크 http://api.jquery.com/map/

.map( callback(index, domElement) )Returns : jQuery

개요 : 현재 선택 집합의 각 요소들에 함수를 사용하면 반환되는 값을 포함하는 새로운 jQuery 객체를 얻어낼 수 있습니다.

  • .map( callback(index, domElement) )
  • callback(index, domElement) 현재 세트의 각 요소들을 호출하는 함수 객체(ㅡㅡ; 뭘까요?)

위쪽에 설명된 내용들은 사실 잘 와닿지 않습니다. 제 발번역 탓도 있지만 직관적으로 설명이 되어 있지 않습니다. 이 함수를 테스트해 보았습니다. 결과적으로는 함수 내에 있는 연산을 통해 반환되는 결과값들이 배열과 같은 모양으로 구성된다는 것입니다. 아래 예제들을 보시면 더 쉽게 아실수 있을 겁니다.

반환되는 jQuery로 감싸진 배열(jQuery-wrapped array)을 아주 일반적인 함수인 get()을 사용하여 기본 배열로 변환시킬 수 있습니다. 이 부분은 map() 함수는 get()함수와 쌍으로 논다로 이해하시면 좋으실 것 같습니다.

.map() 는 요소의 집합에 가져오거나 입력할 때 아주 유용하게 사용할 수 있는 조금 특별한 함수입니다. 아래 예를 통해 체크박스의 값을 꺼내는 걸 보겠습니다.

<form method="post" action="">
  <fieldset>
    <div>
      <label for="two">2</label>
      <input type="checkbox" value="2" id="two" name="number[]">
    </div>
    <div>
      <label for="four">4</label>
      <input type="checkbox" value="4" id="four" name="number[]">
    </div>
    <div>
      <label for="six">6</label>
      <input type="checkbox" value="6" id="six" name="number[]">
    </div>
    <div>
      <label for="eight">8</label>
      <input type="checkbox" value="8" id="eight" name="number[]">
    </div>
  </fieldset>
</form>

체크박스의 ID요소의 값을 콤마로 연결된 문자열로 만들어 보겠습니다.

$(':checkbox').map(function() {
  return this.id;
}).get().join(',');

위 스크립트의 결과값은 "two,four,six,eight" 입니다.

설명 들어갑니다. 1라인에서 체크박스들을 선택하는 선택자를 사용하여 map 함수를 사용합니다. 2라인에서의 this는 선택된 체크박스 각각을 의미합니다. 그렇다면 각각의 체크박스들의 id값을 반환(return)하게 됩니다. 3라인의 get() 함수를 사용하여 일반적인 배열로 변환시킨 후 각 배열 요소를 join() 함수를 사용해 콤마 문자열을 사용하여 이어 붙입니다. 그럼 짜잔 하고 결과값이 나오게 되네요.

어렵지 않으시죠? map() 함수는 결국 리턴된 결과값을 배열의 형태로 구성해 줍니다. 내부적으로 어떻게 만들어 지는지는 따져봐야 겠지만서도 일단은 map의 의미는 일정한 형태의 결과셋정도로 생각하시면 되겠네요.

callback 함수 내의 this 키워드는 각 요소들을 의미하게 됩니다. 함수는 개별적인 데이터 아이템을 리턴하거나 결과집합에 데이터 아이템 배열을 삽입할 수도 있습니다. 만약 배열이 반환됬다면 배열안의 요소들은 집합안에 삽입됩니다. 만약 결과값이 null 이거나 undefined 라면 삽입되지 않습니다.

위 설명은 이해가 쉽지 않았습니다. 의미는 무슨 소리인지 알겠지만 정작 문장의 해석이 어렵네요. 여차저차해서 결과가 정상적으로 있다면 배열로 데이터가 구성된다는 것만 잊지 않으시면 되겠습니다.

예 제  
폼 안에 있는 값들을 꺼내서 하나의 문자열로 만들어 보겠습니다.

<!DOCTYPE html>
<html>
<head>
  <style>
  p { color:red; }
  </style>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  <p><b>Values: </b></p>
  <form>
    <input type="text" name="name" value="John"/>

    <input type="text" name="password" value="password"/>
    <input type="text" name="url" value="http://ejohn.org/"/>

  </form>
<script>
    $("p").append( $("input").map(function(){
      return $(this).val();
    }).get().join(", ") );

</script>

</body>
</html>

미리보기

결과를 보시면 무슨 내용인지 단박에 아실 수 있을 겁니다.

그래도 잠깐 훑어보고 갈까요. 19라인을 보시면 p 태그를 선택해서 append()함수로 무언가를 추가하고 있습니다. input 태그를 찾아서 map()함수의 인자로 요소 집합을 넘겨주네요. 20라인에서는 $(this)를 이용해서 현재 input 태그를 jQuery 객체화 한 후 val() 함수를 사용해 해당 요소의 value 값을 꺼내어 return해 줍니다. 21라인에서 넘겨진 결과 map을 get() 함수를 사용하여 일반 배열화 시킨 후 join()으로 문자열을 만들어 줍니다. 그 만들어진 문자열이 19라인의 append() 함수 때문에 p 태그 안에 추가되게 됩니다. 결과를 보시면 Values : 다음에 나온는 것들임을 알수 있습니다. 짜잔~ 와 닿으시죠??

 

예 제  
함수적으로 복잡스럽게 사용하는 예제입니다.

<!DOCTYPE html>
<html>
<head>
  <style>
  body { font-size:16px; }
  ul { float:left; margin:0 30px; color:blue; }
  #results { color:red; }
  </style>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  <ul>
    <li>First</li>
    <li>Second</li>
    <li>Third</li>

    <li>Fourth</li>
    <li>Fifth</li>
  </ul>
  <ul id="results">

  </ul>
<script>
var mappedItems = $("li").map(function (index) {
  var replacement = $("<li>").text($(this).text()).get(0);
  if (index == 0) {
    /* make the first item all caps */
    $(replacement).text($(replacement).text().toUpperCase());
  } else if (index == 1 || index == 3) {
    /* delete the second and fourth items */
    replacement = null;
  } else if (index == 2) {
    /* make two of the third item and add some text */
    replacement = [replacement,$("<li>").get(0)];
    $(replacement[0]).append("<b> - A</b>");
    $(replacement[1]).append("Extra <b> - B</b>");
  }

  /* replacement will be a dom element, null, 
     or an array of dom elements */
  return replacement;
});
$("#results").append(mappedItems);

</script>

</body>
</html>

미리보기

"응?? 이게 뭐야??" 하고 계시죠?? ^^ 저도 첨에 넘 복잡해서 잘 모르겠더라구요. 설명하기는 너무 길어질 것 같습니다. 간단하게 보면 이번 예제의 핵심은 index 라는 인자를 사용하여 각 요소별로 처리를 할 수 있다는 것입니다. if문을 보시면 index가 0일때, 1 또는 3일때, 2일때 하는 행동이 다른 것을 보실 수 있을 겁니다. 참고적으로 0일때는 첫 li가 되고 그 안의 text를 toUpperCase() 함수를 사용하여 대문자로 만들고 있습니다. 오른쪽 빨간색 텍스트가 결과가 됩니다. FIRST가 보이시죠? 마찬가지로 1 또는 3일때는 요소를 삭제하고 2일 때는 배열 요소로 접근하여 특정 단어들을 내용에 추가하고 있는 것을 알수 있습니다.

차분히 쳐다보시면 보이실 겁니다. 단 무지 졸리게 될 수도 있습니다. :-)

 

예 제  
버튼을 누르면 div의 높이가 동일해 집니다.

<!DOCTYPE html>
<html>
<head>
  <style>
div { width: 40px; float:left; }
input { clear:left}
  </style>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
  

<input type="button" value="equalize div heights">

<div style="background:red; height: 40px; "></div>
<div style="background:green; height: 70px;"></div>
<div style="background:blue; height: 50px; "></div>


<script>
$.fn.equalizeHeights = function() {
  var maxHeight = this.map(function(i,e) {
    return $(e).height();
  }).get();
  
  return this.height( Math.max.apply(this, maxHeight) );
};

$('input').click(function(){
  $('div').equalizeHeights();
});

</script>

</body>
</html>

미리보기

이번 예제 또한 아주 재미있습니다. $.fn.function_name = function () {}; 형태로 jQuery용 함수를 만들수 있는 것도 재미 있습니다. 그리고 map() 함수의 인자로 index와 element를 동시에 줄 수 있는 모습도 보실 수 있습니다. 예제의 e 인자가 선택된 요소집합의 각 요소들이 됩니다. 아래쪽 input 을 클릭하면 $('div')를 찾아서 equalizeHeights() 함수를 호출하는 것을 보실수 있을겁니다. 즉 div 들을 인자로 하여 map() 함수에 던질 수 있는 기법입니다.

 

사실 좀 직관적이지 않아서 어려운 내용일 수도 있습니다. 예제에서 나온 기법들도 쉽게 생각해내기 어려운 것이기도 하구요. 뭐 그렇다고 기죽을 필요는 없습니다. 우리는 이미 예제를 봤고 언제가는 기억이 날테니까요. 자 기운들 내시고 앞으로~

그럼 즐프하세요.

※ 본 예제는 http://www.jquery.com 에 있는 내용임을 밝힙니다.