jQuery / Method / jQuery.inArray()

jQuery.inArray(value, array, fromIndex)는 배열에서 값을 찾아 처음 일치하는 인덱스를 반환하고, 없으면 -1을 반환합니다. 존재 여부는 index !== -1로 판정합니다. 0은 첫 위치에서 찾았다는 뜻이므로 반환값을 그대로 if 조건에 넣으면 잘못 판단할 수 있습니다.

반환값은 true·false가 아니라 위치

jQuery.inArray() 공식 문서의 인수 순서는 찾는 값, 배열, 선택적인 시작 인덱스입니다. jQuery 전역 유틸리티이므로 $.inArray(...)와 jQuery.inArray(...)로 호출합니다. 선택한 DOM 요소에 $(selector).inArray(...)를 연결하는 메서드가 아닙니다.

반환값 뜻 Boolean(index) index !== -1
0 첫 항목에서 찾음 false true
1 이상의 정수 해당 인덱스에서 찾음 true true
-1 검색 범위에서 못 찾음 true false

if (index)나 index > 0은 첫 항목을 놓칩니다. 못 찾은 -1도 JavaScript 조건에서는 참으로 취급되므로 부정 연산만 붙여도 해결되지 않습니다. 반환값을 -1과 비교하거나 0 이상인지 명시적으로 확인합니다.

자료형과 시작 위치를 바꾸는 전체 실습

전체 코드를 UTF-8의 inarray-demo.html로 저장한 뒤 브라우저에서 엽니다. 공식 jQuery 파일 4.0.0을 CDN(Content Delivery Network, 콘텐츠 전송 네트워크)에서 읽을 인터넷 연결이 필요하며 별도 설치는 없습니다. 숫자·문자열, 양수·음수 시작 위치, 빈 배열과 아래 비교를 3.7.1과 4.0.0에서 실행했습니다.

배열은 [0, "0", "alpha", 0]입니다. Value는 정해 둔 선택지에서 값을 가져오며 문자열 표현식을 실행하지 않습니다. From index만 Number()로 바꿔 시작 위치로 사용합니다.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Search an array with inArray</title>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
  <style>
    body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 24px auto; padding: 16px; }
    button, select { font: inherit; margin: 4px; }
    pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  </style>
</head>
<body>
  <h1>Find an index rather than a boolean</h1>
  <p>Array: [0, "0", "alpha", 0]</p>
  <label for="value">Value:</label>
  <select id="value"><option value="number">0 (number)</option><option value="string">0 (string)</option><option value="alpha">alpha</option><option value="missing">missing</option></select>
  <label for="from">From index:</label>
  <select id="from"><option>0</option><option>1</option><option>3</option><option>9</option><option>-1</option></select>
  <button type="button" id="search">Search</button>
  <button type="button" id="reset">Reset</button>
  <pre id="result" aria-live="polite"></pre>
  <script>
    $(function () {
      const array = [0, "0", "alpha", 0];
      const choices = { number: 0, string: "0", alpha: "alpha", missing: "missing" };
      function search() {
        const value = choices[$("#value").val()];
        const fromIndex = Number($("#from").val());
        const index = $.inArray(value, array, fromIndex);
        const found = index !== -1;
        $("#result").text(`value=${JSON.stringify(value)} (${typeof value})\nindex=${index}\nfound=${found}\nBoolean(index)=${Boolean(index)}`);
      }
      $("#value, #from").on("change", search);
      $("#search").on("click", search);
      $("#reset").on("click", function () {
        $("#value").val("number");
        $("#from").val("0");
        search();
      });
      search();
    });
  </script>
</body>
</html>

초기에는 숫자 0을 첫 위치에서 찾습니다.

value=0 (number)
index=0
found=true
Boolean(index)=false
  1. Value를 0 (string)으로 바꾸면 index는 1입니다. 숫자 0과 문자열 "0"을 구분합니다.
  2. 0 (number)로 돌아가 From index를 1로 바꾸면 index는 3입니다. 첫 숫자 0을 건너뛰고 뒤쪽의 같은 값을 찾습니다.
  3. From index를 3으로 바꿔도 해당 위치를 포함하므로 index는 3입니다.
  4. 9는 배열 길이를 넘으므로 index -1, found false입니다. Boolean(index)는 여전히 true임을 비교합니다.
  5. -1은 끝에서 한 칸인 인덱스 3부터 검색해 숫자 0을 찾습니다.
  6. 시작을 0으로 두고 alpha나 missing을 고르면 각각 2와 -1입니다. Reset은 숫자 0·시작 0을 복원하고 Search는 현재 조건으로 다시 검색합니다.

엄격한 비교와 fromIndex 범위

비교는 ===와 같은 엄격한 비교입니다. 문자열 "0"을 숫자 0으로 자동 변환하지 않으며, 문자열의 일부만 일치하는 검색도 아닙니다. 입력 컨트롤에서 얻은 값이 문자열인지 숫자인지 먼저 정하고, 변환이 필요하면 허용할 값과 실패 처리를 명확히 합니다.

시작 위치를 생략하면 0입니다. 음수는 배열 끝을 기준으로 시작 위치를 계산하지만, 검색 방향은 계속 앞에서 뒤입니다. 시작이 배열보다 훨씬 앞이면 0부터, 길이 이상이면 찾지 못한 -1입니다. 결과는 검색 시작부터의 상대 번호가 아니라 원래 배열의 인덱스입니다. 같은 값이 여러 번 있어도 시작 위치 이후의 첫 일치만 반환합니다.

객체는 속성이 같은지만 비교하지 않습니다. 같은 객체 참조인지가 중요합니다. 다음 완전한 부분 코드를 개발자 도구 Console에서 실행하면, 같은 객체와 새 객체, NaN 및 네이티브 대안을 비교할 수 있습니다.

const item = { id: 1 };
console.log(`same object=${$.inArray(item, [item])}`);
console.log(`new object=${$.inArray({ id: 1 }, [item])}`);
console.log(`NaN index=${$.inArray(NaN, [NaN])} | includes=${[NaN].includes(NaN)}`);
console.log(`empty=${$.inArray("a", [])}`);
const array = ["a", "b", "a"];
console.log(`start 1=${$.inArray("a", array, 1)} | start -1=${$.inArray("a", array, -1)}`);
console.log(`native index=${array.indexOf("a", 1)} | native found=${array.includes("a", 1)}`);
same object=0
new object=-1
NaN index=-1 | includes=true
empty=-1
start 1=2 | start -1=2
native index=2 | native found=true

indexOf·includes 선택과 후속 처리

일반 배열에서 위치가 필요하면 네이티브 array.indexOf(value, fromIndex)도 사용할 수 있습니다. jQuery가 필요 없는 코드에 배열 검색 하나를 위해 jQuery를 추가할 필요는 없습니다. 인수 순서는 $.inArray(value, array)와 달리 배열에 .indexOf(value)를 호출하는 형태입니다.

존재 여부만 필요하면 array.includes(value, fromIndex)가 true·false를 직접 반환합니다. 다만 비교 규칙이 완전히 같지는 않습니다. NaN은 $.inArray()와 indexOf()로 찾으면 -1이지만 includes()로는 true입니다. 객체 참조 비교와 숫자·문자열 구분은 계속 고려해야 합니다.

검색 결과로 배열 항목을 지우려면 -1이 아닌지 검사한 후 후속 작업을 합니다. 못 찾은 -1을 그대로 splice()의 위치로 사용하면 마지막 항목을 지울 수 있습니다. 예상과 다르면 값의 자료형, 인수 순서, 시작 위치, 객체 참조와 원래 배열이 바뀌었는지를 확인합니다.