코딩/Javascript

자바스크립트 배열(Array) length 속성 파헤치기

드리프트 2021. 6. 10. 11:58
728x170

 

 

자바스크립트 개발자는 매일 배열(Array)을 다룹니다.

 

자바스크립트 배열은 컬렉션이기 때문에 우리가 쿼리 할 중요한 속성 중 하나는 항목 수입니다.

 

즉, Array.prototype.length입니다.


JavaScript에서 길이가 항상 기존 요소의 수를 나타내는 것은 아니며 (희소 배열의 경우)이 속성을 수정하면 요소가 제거 될 수 있습니다.


이 속성 뒤에 숨은 마법을 알아 보겠습니다.

 

자바스크립트에서 정의하는 배열의 길이는 배열에서 가장 높은 인덱스보다 더 큰 양수의 32 비트 정수값입니다.

 

이 속성은 특정 배열 유형에 대해 다르게 작동합니다. 

 

배열은 요소의 인덱스가 0에서 시작하는 연속적인 인덱스를 가질 때 조밀하다고 합니다.

 

예를 들어 [1, 3, 4]는 인덱스가 연속적이기 때문에 조밀합니다.

 

인덱스 0, 인덱스 1, 인덱스 2로 인덱스하기 때문에 인덱스 사이의 간격이 조밀하다고 합니다.

 

예를 들어 [1,, 4, 6]은 요소 인덱스가 연속적이지 않기 때문에 희소합니다.인덱스 0, 인덱스 2 및 인덱스 3으로 인덱싱하기 때문입니다.

 

 

배열의 요소 수로서의 길이

 

길이의 일반적인 용도는 요소 수를 결정하는 것입니다.

 

밀도가 높은 컬렉션 유형에 적합합니다.

 

var fruits = ['orange', 'apple', 'banana']; //fruits 배열은 조밀한 배열
console.log(fruits.length); // 실젝 배열 요소 갯수인 3을 출력

fruits.push('mango');
console.log(fruits.length); // 한개의 요소가 추가된 후 4를 출력

var empty = [];
console.log(empty.length); // 비어있는 배열, 0을 출력

조밀한 배열은 비어 있지 않으며 항목 수는 최고 인덱스 + 1에 해당합니다.

 

[3, 5, 7, 8]에서 가장 높은 인덱스는 요소 8의 3이므로 배열 크기는 3 + 1 = 4입니다.

 

 

가장 높은 지수보다 큰 숫자의 길이

 

희소 배열에서 길이는 가장 높은 인덱스보다 크지만 실제 요소 수를 나타내지는 않습니다.

 

길이를 쿼리 할 때 요소 개수보다 큽니다.

 

배열의 간격 때문에 발생합니다.

 

var animals = ['cat', 'dog', , 'monkey']; // animals 배열은 희소한 배열입니다.
console.log(animals.length); // 4를 출력하지만, 실젝 요수 갯수는 3개입니다.

var words = ['hello'];
words[6] = 'welcome'; //가장 큰 인덱스는 6이고, words 배열은 희소합니다.
console.log(words.length); //7을 출력합니다, 가장 큰 인덱스가 6이기 때문입니다.

요소를 추가하거나 제거 할 때 가장 높은 인덱스만을 기준으로 길이가 변경됩니다.

 

가장 높은 인덱스에 영향을 주지 않는 배열 수정은 길이를 수정하지 않습니다

 

(예 : delete 사용시)

 

var colors = ['blue', 'red', 'yellow', 'white', 'black'];
console.log(colors.length); // 5를 출력

delete colors[0]; // 첫번째 요소인 'blue' 제거. 
                  // 여기서 배열이 희소해 진다고 표현합니다.

console.log(colors.length); // 여전히 5를 출력, 왜냐하면 가장 큰 인덱스값이 4이고 
              // 가장 큰 인덱스값은 변경되지 않았기 때문입니다.

 

 

길이 수정

 

이전 설명에서 길이는 읽기 전용이었습니다.

 

그러나 JavaScript는 이 속성도 수정할 수 있습니다.

 

길이 수정은 새 값과 기존의 가장 높은 인덱스에 따라 배열에 영향을 줍니다.

 

요소를 제거하거나 배열을 희소하게 만들 수 있습니다.


새 길이 번호가 가장 높은 인덱스보다 작거나 같으면 인덱스가 새 크기보다 크거나 같은 요소가 제거됩니다.

 

배열 끝에서 요소를 제거하는 유용한 시나리오입니다.

 

var numbers = [1, 3, 5, 7, 8];

numbers.length = 3; // 배열의 길이(length)를 수정 
console.log(numbers) // [1, 3, 5]를 출력, 요소 7과 8은 제거됨.

가장 높은 인덱스보다 큰 숫자를 사용하거나 현재 길이보다 큰 숫자를 사용하는 경우 배열이 희소 화됩니다.

 

그러나 이런 방식은 거의 쓰이지 않습니다.

 

var osTypes = ['OS X', 'Linux', 'Windows'];

osTypes.length = 5; // 희소한 배열로 바꾸게 됩니다. 인덱스 3과 인덱스 4는 존재하지는 않습니다.

console.log(osTypes); // ['OS X', 'Linux', 'Windows', , , ]이라고 출력됨.

길이에 숫자와 다른 유형을 할당 할 수 있습니다.

 

JavaScript는 프리미티브를 숫자로 변환합니다.

 

변환 결과가 NaN이거나 0 미만인 경우 오류가 발생합니다. Uncaught RangeError : Invalid array length.

 

var numbers = [1, 4, 6, 7];
numbers.length = '2'; // '2' 는 숫자 2로 변환됨.
numbers.length = 'not-number'; // 에러 발생 Uncaught RangeError: Invalid array length
numbers.length = -2; // 에러 발생 Uncaught RangeError: Invalid array length

 

안전한 코딩

 

배열 길이 수정, 삭제로 요소 제거, [newIndex]로 요소 추가는 희소 배열을 만들어 잠재적인 문제의 원인이됩니다.

 

결과적으로 길이 값이 일치하지 않습니다.

 

JavaScript는 더 안전한 대안을 제공합니다.

 

배열 끝에 요소를 추가하려면 Array.prototype.push()를 사용하고 가장 최신의 요소를 제거할려면 pop()을 사용하세요.

 

처음에 요소를 삽입하려면 unshift()를 사용하고 첫 번째 항목을 제거하려면 shift()를 사용하세요.

 

더 복잡한 삽입, 삭제 또는 교체의 경우 splice() 함수도 충분히 강력합니다.

 

var companies = ['Apple', 'Dell'];

// 배열끝에 요소 추가
companies.push('ASUS');

// ['Apple', 'Dell', 'ASUS'] 출력
console.log(companies);

// 마지막 요소 삭제
companies.pop(); 

// ['Apple', 'Dell'] 출력
console.log(companies);

// 첫번째 요소 삭제
companies.shift();

// ["Dell"] 출력
console.log(companies);

// 배열 끝에 "Microsoft" 와 "HP" 추가
companies.splice(1, 0, "Microsoft", "HP");

// ["Dell", "Microsoft", "HP"] 출력
console.log(companies);

// 3을 출력. 위와 같이 배열을 추가 삭제해도 배열 상태는 조밀한 상태로 유지
console.log(companies.length);

드물게 배열이 희소해 질 수 있는 상황이 있습니다.

 

길이에 의존하여 요소 수를 결정하는 것은 안전하지 않습니다.

 

누락 된 요소를 처리하는 도우미 함수를 사용하십시오.

 

/**
 * Count the number of elements in a sparse array
 * @param {Array} collection
 * @return {number}
 */
function count(collection) {
  var totalCount = 0;
  for (var index = 0; index < collection.length; index++) {
    if (index in collection) {
      totalCount++;
    }
  }
  return totalCount;
}

in 연산자는 객체에 속성이 있는지 확인합니다. 

 

특정 인덱스에 요소가 있는지 확인하는 데 완벽하게 작동합니다.

 

 

결론

 

위에서 볼 수 있듯이 길이는 복잡한 동작을 가진 속성입니다.


대부분 개발자가 의도한 데로 작동하지만 희소 배열을 처리하고 길이를 수정할 때는 예방 조치를 취하는 것이 좋습니다.


그래서 길이(length) 속성을 수정하지 않고, 배열에 추가하거나 삭제할 때는 splice() 메서드를 사용하는 것입니다.

 

 

그리드형