[js] 기본적인 배열 / 버퍼와 뷰

기본적인 배열


배열 생성

아래 구문들은 동일한 배열을 생성한다.

const arr1 = new Array(a, b, ..., n);
const arr2 = Array(a, b, ..., n);
const arr3 = [a, b, ..., n];

길이가 0이 아니지만 요소는 없는 배열

const arr1 = new Array(7);
const arr2 = Array(7);
const arr3 = [];
arr3.length = 7;

객체의 속성에 배열 할당하기

const obj = {};
obj.prop = [a, b];

또는

const obj = { prop: [a, b] };
obj.prop; // [a, b]

배열의 요소도 속성이므로 속성 접근자를 사용하여 접근할 수 있다.

const arr = ["one", "two", "three"];
arr[2]; // three
arr["length"]; // 3

배열 채우기

const myArray = new Array("Hello", myVar, 3.14159);
const myArray = ["Mango", "Apple", "Orange"];

const emp = [];
emp[0] = "Casey Jones";
emp[1] = "Phil Lesh";
emp[2] = "August West";

 

배열 연산자에 정수가 아닌 값을 제공하면 배열 요소 대신 배열을 나타내는 객체에 속성이 생성된다.

const arr = [];
arr[3.4] = "Oranges";
console.log(arr.length); // 0
console.log(Object.hasOwn(arr, 3.4)); // true

length 속성에 값을 할당할 수 있습니다. 저장된 항목 수보다 작은 값을 쓰면 배열이 잘립니다. 0을 쓰면 배열이 완전히 비워집니다.

const cats = ["Dusty", "Misty", "Twiggy"];
console.log(cats.length); // 3

cats.length = 2;
console.log(cats); // [ 'Dusty', 'Misty' ] - Twiggy 값이 제거되었습니다

cats.length = 0;
console.log(cats); // []; cats 배열은 비었습니다

cats.length = 3;
console.log(cats); // [ <3 empty items> ]

배열의 요소 반복 처리

배열의 어떤 요소도 불리언 컨텍스트에서 false로 평가되지 않는다는 것을 알고 있다면 (예를 들어 배열의 요소가 DOM노드로만 구성된 경우) 보다 효율적인 코드 관용구를 사용할 수 있다.

const divs = document.getElementsByTagName("div");
for (let i = 0, div; (div = divs[i]); i++) {
  // 조건 (div = divs[i])가 실행된 뒤 div에 값이 대입되어, divs[0] (배열의 첫 번째 요소)가 div 변수에 할당된다.
  /* Process div in some way */
}

이렇게 하면 배열의 길이를 확인하는 오버헤드를 피할 수 있으며, 루프가 반복될 때마다 div 변수가 현재 항목에 재할당되어 편의성을 높일 수 있다.

 

forEach()

할당되지 않은 값은 forEach 반복문에서 반복되지 않고 의도적으로 undefined를 할당한 경우에는 출력된다.

const colors = ["red", undefined, "green", , "blue"];
colors.forEach((color) => console.log(color));
// red
// undefined
// green

배열의 메서드

출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array

Array에 사용할 수 있는 메서드는 다음과 같다.
concat() copyWithin() every() filter() flat() flatMap() forEach() indexOf() lastIndexOf() map() reduce() reduceRight() reverse() slice() some()sort() splice() entries() fill() find() findIndex() findLast() findLastIndex() includes() join() keys() toLocaleString() values() pop() push() toReversed() toSorted() toSpliced() with()

concat() 메서드는 두 개의 배열을 합쳐 새로운 배열을 반환

let myArray = ["1", "2", "3"];
myArray = myArray.concat("a", "b", "c");
// myArray is now ["1", "2", "3", "a", "b", "c"]

join() 메서드는 배열의 모든 요소를 하나의 문자열로 연결하여 반환

const myArray = ["Wind", "Rain", "Fire"];
const list = myArray.join(" - "); // list is "Wind - Rain - Fire"

push() 메서드는 하나 혹은 그 이상의 요소를 배열의 마지막에 추가하고 추가된 요소를 포함한 length를 반환

const myArray = ["1", "2"];
a = myArray.push("3"); // myArray is now ["1", "2", "3"], a is 3

 

pop() 메서드는 배열의 마지막 요소를 제거하고 그 제거된 요소를 반환

const myArray = ["1", "2", "3"];
const a = myArray.pop();
// myArray is now ["1", "2"], a is "3"

shift() 메서드는 배열의 첫번째 요소를 제거하고 그 제거된 요소를 반환

const myArray = ["1", "2", "3"];
const first = myArray.shift();
// myArray is now ["2", "3"], first is "1"

 

unshift() 메서드는 하나 혹은 그 이상의 요소를 배열의 앞쪽에 추가하고 추가한 요소를 포함한 길이를 반환

const myArray = ["1", "2", "3"];
myArray.unshift("4", "5");
// myArray becomes ["4", "5", "1", "2", "3"]

 

slice() 메서드는 배열의 특정 부분을 추출하여 그 추출된 부분을 포함하는 새로운 배열을 반

let myArray = ["a", "b", "c", "d", "e"];
myArray = myArray.slice(1, 4); // [ "b", "c", "d"]
// 인덱스 1에서 시작하여 인덱스 3까지의 모든 요소

 

at() 메서드는 배열의 지정된 인덱스에 있는 요소를 반환하거나 인덱스가 범위를 벗어난 경우 undefined을 반환. 특히 배열의 끝에서 요소에 접근하는 음수 인덱스에 사용

const myArray = ["a", "b", "c", "d", "e"];
myArray.at(-2); // "d", the second-last element of myArray

 

The splice() 메서드는 배열에서 요소를 제거한 후 (선택적으로) 대체. 이 메서드는 배열에서 제거된 항목을 반환

const myArray = ["1", "2", "3", "4", "5"];
myArray.splice(1, 3, "a", "b", "c", "d");
// myArray 는 이제 ["1", "a", "b", "c", "d", "5"] 가 됩니다.
// 이 코드는 첫 번째 인덱스("2"값이 있는 곳)에서 시작하여
// 3개의 요소를 삭제한 후 그 자리에 연속된 모든 요소를 모두 삽입합니다.

 

reverse() 메서드는 배열의 요소를 첫 번째 배열 요소가 마지막이 되고 마지막 요소가 첫 번째가 되는 식으로 배열의 요소를 바꾼다. 배열에 대한 참조를 반환

const myArray = ["1", "2", "3"];
myArray.reverse();
// transposes the array so that myArray = ["3", "2", "1"]

flat() 메서드는 지정된 깊이까지 재귀적으로 연결된 모든 하위 배열 요소가 포함된 새 배열을 반환

let myArray = [1, 2, [3, 4]];
myArray = myArray.flat();
// myArray is now [1, 2, 3, 4], since the [3, 4] subarray is flattened

sort() 메서드는 배열의 요소를 새로운 배열이 아닌 주어진 배열 내에서 정렬하고 배열에 대한 참조를 반환

const myArray = ["Wind", "Rain", "Fire"];
myArray.sort();
// 배열을 정렬하게 되어서 이제 myArray = ["Fire", "Rain", "Wind"]

sort() 메서드는 어떻게 해당 배열의 요소를 정렬할지 결정하는 콜백 함수를 인자로 받을 수 있다. 콜백 함수는 배열에서 온 두 값을 두 개의 인수로 사용하여 호출된다. 이 함수는 이 두 값을 비교하여 두 값의 순서를 나타내는 양수, 음수 또는 0을 반환한다. 예를 들어 다음은 문자열의 마지막 문자를 기준으로 배열을 정렬한다.

const sortFn = (a, b) => {
  if (a[a.length - 1] < b[b.length - 1]) {
    return -1; // 음수 => a < b, a 는 b 앞으로 옵니다.
  } else if (a[a.length - 1] > b[b.length - 1]) {
    return 1; // 양수 => a > b, a 는 b 뒤에 옵니다.
  }
  return 0; // 0 => a = b, a 와 b 는 원래 순서를 유지합니다.
};
myArray.sort(sortFn);
// sorts the array so that myArray = ["Wind","Fire","Rain"]

정렬 시스템에 의해 a가 b보다 작으면, -1(또는 임의의 음수)을 반환

정렬 시스템에 의해 a가 b보다 크면, 1(또는 임의의 양수)을 반환

a와 b가 동등하다 간주되면 0을 반환

 

indexOf() 메서드는 배열에서 searchElement를 찾아서 첫 번째 일치하는 요소의 인덱스를 반환

const a = ["a", "b", "a", "b", "a"];
console.log(a.indexOf("b")); // 1
console.log(a.indexOf("b", 2)); // b의 검색을 인덱스 2에서부터 시작한다.
console.log(a.indexOf("z")); // -1

const a = ["a", "b", "c", "d", "a", "b"];
console.log(a.lastIndexOf("b")); // 5
console.log(a.lastIndexOf("b", 4)); // 1 // b의 검색을 인덱스 4에서부터 역으로 시작한다.
console.log(a.lastIndexOf("z")); // -1

 

forEach() 메서드는 배열의 모든 요소에 대해 반복적으로 주어진 callback 함수를 실행하며 undefined를 반환

const a = ["a", "b", "c"];
a.forEach((element) => {
  console.log(element);
});
// Logs:
// a
// b
// c

 

콜백을 받는 forEach 메서드는 어떤 방식으로든 전체 배열을 반복하기 때문에 반복적인(iterative) 메서드로 알려져 있다. 각 메서드는 thisArg라는 선택적 두 번째 인수를 받는다. forEach(callbackFn, thisArg) 이 인수가 제공되면 thisArg는 콜백 함수 안에 있는 this 키워드의 값이 된다.

class Counter {
  constructor() {
    this.sum = 0;
    this.count = 0;
  }

  add(array) {
    // 오직 함수 표현식만 자신의 this 바인딩을 가집니다.
    array.forEach(function countEntry(entry) {
      this.sum += entry;
      ++this.count;
    }, this); // 이 this는 Class의 this가 되므로
  }
}

const obj = new Counter();
obj.add([2, 5, 9]);
console.log(obj.count); // 3
console.log(obj.sum); // 16 // 총 더해진 값인 16이 출력된다.

for문과 forEach

const items = ["item1", "item2", "item3"];
const copyItems = [];

// 전
for (let i = 0; i < items.length; i++) {
  copyItems.push(items[i]);
}

// 후
items.forEach((item) => {
  copyItems.push(item);
});

 

map() 메서드는 배열의 모든 요소에 대해 callback 함수를 실행하고 이 결과를 새로운 배열에 담아 반환

const a1 = ["a", "b", "c"];
const a2 = a1.map((item) => item.toUpperCase());
console.log(a2); // ['A', 'B', 'C']

 

filter() 메서드는 callback 함수가 true를 반환하는 요소를 새로운 배열에 담아 반환

const a1 = ["a", 10, "b", 20, "c", 30];
const a2 = a1.filter((item) => typeof item === "number");
console.log(a2); // [10, 20, 30]

find() 메서드는 callback이 true를 반환하는 첫 번째 항목을 반환

const a1 = ["a", 10, "b", 20, "c", 30];
const i = a1.find((item) => typeof item === "number");
console.log(i); // 10

findLast() 메서드는 callback이 true를 반환하는 마지막 항목을 반환

const a1 = ["a", 10, "b", 20, "c", 30];
const i = a1.findLast((item) => typeof item === "number");
console.log(i); // 30

every() 메서드는 callback이 배열의 모든 항목에 대해 true를 반환하면 true를 반환

function isNumber(value) {
  return typeof value === "number";
}

const a1 = [1, 2, 3];
console.log(a1.every(isNumber)); // true
const a2 = [1, "2", 3];
console.log(a2.every(isNumber)); // false

some() 메서드는 배열에서 적어도 callback이 true를 적어도 한번이라도 반환하면 true를 반환

function isNumber(value) {
  return typeof value === "number";
}

const a1 = [1, 2, 3];

console.log(a1.some(isNumber)); // true
const a2 = [1, "2", 3];
console.log(a2.some(isNumber)); // true
const a3 = ["1", "2", "3"];
console.log(a3.some(isNumber)); // false

버퍼와 뷰

출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Typed_arrays


 1.  버퍼(Buffer)란?
- 임시로 바이너리 데이터를 저장하기 위한 메모리 공간 혹은 바이너리 데이터 자체

2. ArrayBuffer란?
- 자바스크립트에서 구현된 버퍼이다.
- 고정된 크기의 메모리 공간에 바이너리 데이터를 저장하는 객체다.

- ArrayBuffer 콘텐츠를 직접 조작할 수는 없다. 대신에, 형식화 배열 뷰 또는 특정 형식으로 버퍼를 나타내는 DataView를 만들어 버퍼의 콘텐츠를 읽고 쓸 수 있다.

3. ArrayBufferView란?
- ArrayBuffer에 저장된 바이너리 데이터에 접근하는 객체다.
TypedArray(View)DataView 2개가 제공된다.

    3-1. TypedArray(View)란? (형식화 배열)
    - ArrayBufferView의 한 종류이다.

    - 배열 요소의 타입/크기를 개발자가 지정하여 생성할 수 있다.
    - Uint8Array, Uint16Array, Float32Array 등이 있다.

    - TypedArray는 객체가 아니며, UInt8Array, Float32Array 등을 통칭하는 용어일 뿐이다.

 

    3-2. DataView란?

    - 버퍼의 임의 데이터를 읽고 쓰기 위해 getter/setter API를 제공하는 인터페이스이다.

    - 바이트 순서를 제어할 수 있다.

4. ArrayBuffer와 TypedArray의 관계
- TypedArray는 ArrayBuffer에 저장된 바이너리 데이터를 이용해 만드는 배열이다.

 

출처 : https://curryyou.tistory.com/441

 


버퍼와 뷰 사용하기

var buffer = new ArrayBuffer(16); // 고정길이의 버퍼 생성
// 이 시점에서 버퍼는 바이트가 모두 0인, 16바이트 짜리 메모리 덩어리 일 뿐이다. 딱히 할 수 있는 건 없다.

var int32View = new Int32Array(buffer); // buffer를 사용하여 32비트 짜리 부호있는 정수 배열 생성 // 이걸로 버퍼의 데이터를 다룰 것이다.

for (var i = 0; i < int32View.length; i++) { // 이제 보통 배열처럼, 필드에 접근하여 값을 조작할 수 있다.
  int32View[i] = i * 2; // 배열의 네 항목을 값 0, 2, 4, 6으로 채운다. (네 항목 * 4바이트 == 16바이트)
}

형식화 배열을 사용한 뒤 Array 프로토타입을 사용하기 위해 배열로 돌리고 싶을 수 있다. 그럴 땐 Array.form이나 Array.prototype.slice.call(typedArray); 같은 방식으로 작업할 수 있다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Typed_arrays


형식화 배열

javascript에서 Array 객체는 크기가 동적으로 늘었다 줄고, 어떤 JavaScript 값이든 데이터 형식을 혼합하여 가질 수 있다. typed Array(형식화 배열)는 그렇지 않다.

 

형식화 배열의 구현은 버퍼(담고있는는 애)와 뷰(접근하는 애)로 나뉜다.

  • 버퍼 : 데이터 부분을 나타낸다. ArrayBuffer객체에 의해 구현된 객체다. 저장된 값에 접근할 수는 없다.
  • 뷰 : 버퍼에 저장된 값에 엑세스한다. 뷰는 데이터 형, 시작 오프셋, 종료 오프셋을 사용해 데이터를 실제 형식화 배열로 바꾼 뒤 액세스한다. ArrayBufferView의 Typed Array (view)는 Int8, Uint32, Float64처럼 숫자형을 위한 뷰를 제공한다. Uint8ClampedArray 같은 특이한 뷰도 있다.

버퍼와 뷰의 관계

 


형식화 배열을 사용하는 웹 API

  • FileReader.prototype.readAsArrayBuffer() : 지정된 Blob 또는 File의 콘텐츠를 읽는다.
  • XMLHttpRequest.prototype.send()
  • ImageData.data : 0에서 255까지 정수값으로 RGBA 순 데이터를 포함하는 1차원 배열을 나타내는 Uint8ClampedArray이다.