배열은 아니지만 인덱스로 접근할 수 있고
length
속성을 가지는 특수한 배열 처럼 보이는 객체
배열에 있는 기본 기능을 제공하지 않게 하거나 기존 배열과 차별화하여 특정 기능만을 제공하게 한다거나 할 때 사용한다고 한다.
const nodes = document.querySelectorAll('input')
const customLikes = {"0": "hello", "1": "hi", length: 2}
const array = [1,2,3];
typeof nodes; // 'object'
typeof array; // 'object'
Array.isArray(array); // true
Array.isArray(nodes); // false
Array.isArray(customLikes); // false
배열처럼 인덱스로 접근
하여 값을 가져올 수 있고 길이를 가지고 있어
배열처럼 생겼지만
실제로 배열은 아니라 Array.prototype
의 각종 유용한 함수들을 사용하여 다룰 수가 없다.
nodes.map(v => v); // Uncaught TypeError: nodes.map is not a function at <anonymous>:1:7
유사 배열 객체(array-like object)나 반복 가능한 객체(iterable object)를 얕게 복사해 새로운Array 객체를 만듭니다.
Array.from(arrayLike,mapFn,thisArg)
arrayLike
배열로 변환하고자 하는 유사 배열 객체 또는 Iterable 객체
mapFn
배열의 모든 요소에 대해 호출할 매핑 함수
thisArg
mapFn
실행 시 this
로 사용할 값
return
새로운 Array
객체
const customLikes = {"0": "hello", "1": "hi", length: 2}
const customObj = {"0": "hello", "1": "hi"};
const customArray = Array.from(customLikes); // [hello, hi];
const customArray2 = Array.from(customLikes, v => v + " world!");
const customObjToArray = Array.from(customObj); // []
customArray.filter(v => v === "hi"); // ["hi"]
유사 배열을 새로운 배열로 만들어줬기 때문에 map
, reduce
같은 고차함수를 사용할 수 있게 되었다.
주어진 this 값과 배열 (또는 유사 배열 객체) 로 제공되는 arguments 로 함수를 호출합니다.
func.apply(thisArg, argsArray)
다른 객체에 내재된 함수를 내 것 처럼 사용할 수 있게 해준다.
thisArgs
함수를 호출할 대상이 되기 위해 제공되는 this
argsArray
func
가 호출되어야하는 인수를 지정하는 배열
return
지정된 this
로 함수를 호출해 얻은 결과
유사배열 다루기
const customLikes = {"0": "hello", "1": "hi", length: 2}
Array.prototype.push.apply(customLikes, ["hell", "hall"]);
console.log(customLikes); // {0: 'hello', 1: 'hi', 2: 'HELL', 3: 'HALL', length: 4}
const concat =
Array.prototype.reduce.apply(customLikes, [(prev, next) => prev + " " + next]);
// "hell hi HELL HALL"
기존 유사배열의 상태를 직접 조작 가능하고 배열 함수도 사용 가능해진다!
apply만 소개했지만 Func.call, Func.bind도 사용가능
Array.prototype.push.call(customLikes,"hell", "hall");
console.log(customLikes); // {0: 'hello', 1: 'hi', 2: 'HELL', 3: 'HALL', length: 4}
// this를 customLikes로 한 array map 함수를 사용하게끔 원본함수를 복제하여 할당
const likesMapFn = Array.prototype.map.bind(customLikes);
const LikesArray = likesMapFn(v => v + "HELLO");
// ['helloHELLO', 'hiHELLO', 'hellHELLO', 'hallHELLO']
iterable 한 객체의 경우 전개 구문으로 배열로 쉽게 만들 수 있다.
const nodes = document.querySelectorAll('input');
const customLikes = {"0": "hello", "1": "hi", length: 2}
const a = "hell";
const b = [1,2,3];
typeof nodes[Symbol.iterator]; // 'function'
typeof customLikes[Symbol.iterator]; // 'undefined'
typeof a[Symbol.iterator]; // 'function'
typeof b[Symbol.iterator]; // 'function'
const nodeArray = [...nodes]; // [input#id-fname.form-control, input#id-lname.form-control, ...]
const aArray = [...a]; // ['h', 'e', 'l', 'l']
const customLikesToArray = [...customLikes]; // Uncaught TypeError: customLikes is not iterable
const sequence = [...Array(10).keys()].map(v => v + 1);
// [1,2,3,4,5,6,7,8,9,10];
솔직히 아직 유사배열을 직접 사용해야 하는 상황이 있을까? 왜 쓸까? 라는 것에 대해는 잘 이해가 되지 않고 잘 와닿지 않는다.
많이 경험해보고 많은 코드를 보다보면 이해가 될 것이라 믿는다!