Object.entries()
for...in 문은 프로토타입으로 상속받은 속성까지 열거하는 특성이 있으므로
자칫, 뒤통수를 얻어맞기 쉽다. 그래서 가급적이면 for..in 사용은 지양하도록.
for..in 보다는 Object.entries( )
/* bad
for (const key in collection) {
iterator(collection[key], key, collection);
}
*/
😁 for of + Object.entries + 구조분해할당 😃
for (const [key, value] of Object.entries(collection)) {
iterator(collection[key], key, collection);
}
😁Object.entries + forEach 😃
Object.entries(generateEvents).forEach(([key, value]) => {
배열 안에 key, value가 담겨진 배열[ [key:'value'], ...]
로 반환되기 때문에
for...of, forEach등과 함께 사용하면 된다.
단, Object.entries로 반환된 배열은 객체가 정의된 순서와 상관이 없이 나온다.
그래서 배열 순서가 쓸 곳이 있다면, sort()
도 함께 사용해야 한다.
배열에서도 이와 유사한 기능을 하는 배열.entries() 메서드가 있다.
Object.keys()
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.keys(object1));
// ["a", "b", "c"]
Object.keys( ) : 객체의 key 로 이루어진 배열이 반환된다.
for...of와 함께 쓰면 순환하면서 접근할 수 있다.
Object.values()
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.values(object1));
// ["somestring", 42, false]
Object.values( ) : 객체의 value로 이루어진 배열이 반환된다.
for...of와 함께 쓰면 순환하면서 접근할 수 있다.**
hasOwnProperty
obj = new Object();
obj.name = 'colki';
obj = {prop: 'colki'}
/* 직접 소유한 obj 고유속성 */
obj.hasOwnProperty('prop'); // returns true
/* 프로토타입 상속받은 속성 */
obj.hasOwnProperty('toString'); // returns false
obj.hasOwnProperty('hasOwnProperty'); // returns false
__.hasOwnProperty()객체의 속성이 있는 지 확인 후 boolean을 반환.
단 상속 받는 속성이 아닌 직접 가지고 있는 객체의 속성 확인.
const person = {
name: 'hany',
age: 20,
gender: 'female',
address: 'seoul'
};
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
// "name"
// "age"
// "gender"
// "address"
또한 for...in으로 순환할 때 같이 사용하기도 한다.
프로토타입 상속받은 속성도 열거하는 for...in의 허점?을 방지하고 객체만의 속성을 순환하기 위해서 객체.hasOwnProperty(key)
를 사용해서 2중으로 처리해주는 것도 방법이 될 수 있다.
인덱스 0에서 사용한 로직을 인덱스 1, 2, 3... 에도 똑같이 적용된다.
대부분 무난하게 for문을 사용한다.
var n = 0;
var x = 0;
while (n < 3) {
n++;
x += n;
}
// 첫번째 반복; n=1 과 x=1
// 두번째 반복; n=2 과 x=3
// 세번째 반복; n=3 과 x=6
반복을 살펴보면, n을 x에 계속 더하게 된다.
세번째 반복후, n<3 이라는 초건은 더 이상 참이아니가 되므로 반복은 종료된다
while은 조건문이 참일 때 반복문을 실행한다.
while (condition) { statement }
인덱스 0에서 사용한 로직의 결과가 다음 인덱스 1 에 영향을 주게 되는 경우 사용한다.
const a = ['a', 'b', 'c'];
for (const [index, element] of a.entries())
console.log(index, element);
// 0 "a"
// 1 "b"
// 2 "c"
배열.entries()
arr.entries()
object에서는 Object.entries(obj)였지만 배열에서는 구문이 간단하다.
for...of와 함께 사용해서 배열을 순회할 수 있다.
const iterable = [10, 20, 30];
for (const value of iterable) {
console.log(value);
}
// 10
// 20
// 30
/** string에서도 사용가능하다! 😮**/
const iterable = "boo";
for (const value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"
for...of 는 각 요소를 반복
/** 구조분해할당**/
newArray.forEach(([key, value]) => {
iterator(value, key, collection)
})
// for문
for (let i=0; i<items.length; i++) {
copy.push(items[i]);
}
// forEach문
items.forEach(function(item){
copy.push(item);
});
forEach는 콜백함수를 받아서 배열의 각 요소마다 실행한다.
for문(array[i]) 보다 value를 명확하게 표현할 수 있고 잘 읽힌다.
또한 매개변수 2번째인자로 index, 3번째 인자로 배열을 받을 수 있다.
그래서 forEach는 여러개의 배열에 같은 iterator 를 적용할 때 쓰면 편리하다.
단, 모든 요소에 대해 콜백함수를 모두 실행하고 리턴값을 뱉으며 종료되는 메서드이기 때문에, 만약 특정 값을 찾고 그만두는 로직을 구현하고 싶을 때 forEach를 사용한다면 무조건 배열의 마지막 요소까지 돌고 끝이 난다.. 그래서 이럴 경우에는 사용을 지양한다.
예외를 던지지 않고는 forEach( )를 중간에 멈출 수 없습니다. 중간에 멈춰야 한다면 forEach()가 적절한 방법이 아닐지도 모릅니다. -MDN-
const a = [
{a:1},
{b:2},
{c:2}
];
const b = a.map((o, i) => {
o.index = i;
return o;
});
console.log(b);
// [{a: 1, index: 0}, {b: 2, index: 1}, {c: 2, index: 2}]
map이 두번째 인자로 index받는 것을 이용해서
객체로 이루어진 배열에서 각 객체 요소에 key, value를 추가해줄 수 있다.
forEach와 마찬가지로
매개변수 2번째인자로 index, 3번째 인자로 배열을 받을 수 있다.
그래서 map은 여러개의 배열에 같은 iterator 를 적용할 때 쓰면 편리하다.
추가로 배열에서 empty 요소가 있을 경우 순회방법에 따라서
empty를 조회할 수도 하지못할 수도 있다.
for, for ... of 는 empty요소도 확인하여 undefined 값이라도 리턴하지만
forEach처럼 콜백함수를 받는 고차함수는 empty value는 확인하지 않고 패스한다.
const arr = new Array(5);
arr[0] = 1;
arr[4] = 5;
console.log(arr);
// (5) [1, empty × 3, 5]