0%

201218_TIL(ES6 추가 기능_1)

오늘 배운 것

ES6 함수의 추가 기능

화살표함수의 this

화살표 함수는 함수 자체의 this 바인딩을 갖지 않기 때문에 this를 교체할 수 없고 언제나 상위 스코프의 this 바인딩을 참조한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Prefixer {
constructor(prefix) {
this.prefix = prefix;
}

add(arr) {
// add 메서드는 인수로 전달된 배열 arr을 순회하며 배열의 모든 요소에 prefix를 추가한다.
// ①
return arr.map(function (item) {
return this.prefix + item; // ②
// -> TypeError: Cannot read property 'prefix' of undefined
});
}
}

const prefixer = new Prefixer("-webkit-");
console.log(prefixer.add(["transition", "user-select"]));

map 내부 콜백함수의 상위 스코프는 add 메서드이다.

1
2
3
4
5
6
7
8
9
// Bad
class Person {
// 클래스 필드 정의 제안
name = "Lee";
sayHi = () => console.log(`Hi ${this.name}`);
}

const person = new Person();
person.sayHi(); // Hi Lee
1
2
3
4
5
6
7
8
class Person {
constructor() {
this.name = "Lee";
// 클래스가 생성한 인스턴스(this)의 sayHi 프로퍼티에 화살표 함수를 할당한다.
// sayHi 프로퍼티는 인스턴스 프로퍼티이다.
this.sayHi = () => console.log(`Hi ${this.name}`);
}
}

sayHi 클래스 필드에 할당한 화살표 함수의 상위 스코프는 constructor다. 따라서 sayHi 클래스 필드에 할당한 화살표 함수 내부에서 참조한 this는 constructor 내부의 this 바인딩과 같다.

하지만 클래스 필드에 할당한 화살표 함수는 프로토타입 메서드가 아니라 인스턴스 메서드가 된다. 따라서 메서드를 정의할 때는 ES6 메서드 축약 표현으로 정의한 ES6 메서드를 사용하는 것이 좋다.

arguments

화살표 함수는 함수 자체의 arguments 바인딩을 갖지 않는다. 따라서 화살표 함수 내부에서 arguments를 참조하면 this와 마찬가지로 상위 스코프의 arguments를 참조한다.

따라서 화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야 한다.

Rest 파라미터

1
2
3
4
5
6
function foo(...rest) {
// 매개변수 rest는 인수들의 목록을 배열로 전달받는 Rest 파라미터다.
console.log(rest); // [ 1, 2, 3, 4, 5 ]
}

foo(1, 2, 3, 4, 5);

Rest 파라미터와 arguments 객체

arguments 객체는 배열이 아닌 유사 배열 객체이므로 배열 메서드를 사용하려면 Function.prototype.call이나 Function.prototype.apply 메서드를 사용해 arguments 객체를 배열로 변환해야 하는 번거로움이 있었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
unction sum() {
// 유사 배열 객체인 arguments 객체를 배열로 변환한다.
// var array = Array.prototype.slice.call(arguments);

// 위와 동일
const array = [...arguments];

return array.reduce(function (pre, cur) {
return pre + cur;
}, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15

rest 파라미터를 사용하여 가변 인자 함수의 인수 목록을 배열로 직접 전달받을 수 있다. 이를 통해 유사 배열 객체인 arguments 객체를 배열로 변환하는 번거로움을 피할 수 있다.

1
2
3
4
5
function sum(...args) {
// Rest 파라미터 args에는 배열 [1, 2, 3, 4, 5]가 할당된다.
return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15

매개변수 기본값

매개변수에 인수가 전달되었는지 확인하여 인수가 전달되지 않은 경우 매개변수에 기본값을 할당할 필요가 있다. 즉, 방어 코드가 필요하다.

1
2
3
4
5
6
7
8
9
10
function sum(x, y) {
// 인수가 전달되지 않아 매개변수의 값이 undefined인 경우 기본값을 할당한다.
x = x || 0;
y = y || 0;

return x + y;
}

console.log(sum(1, 2)); // 3
console.log(sum(1)); // 1

ES6에서 도입된 매개변수 기본값을 사용하면 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있다.

1
2
3
4
5
6
function sum(x = 0, y = 0) {
return x + y;
}

console.log(sum(1, 2)); // 3
console.log(sum(1)); // 1

배열

1
2
// 값 없이 비어 있는 요소를 위해 메모리 공간을 확보하지 않으며 빈 요소를 생성하지도 않는다.
const arr = [1, , 3];

Array.from

유사 배열 객체(array-like object) 또는 이터러블 객체(iterable object)를 인수로 전달받아 배열로 변환하여 반환

1
2
3
4
5
6
7
8
9
10
11
12
function sum() {
// 유사 배열 객체인 arguments 객체를 배열로 변환한다.
// var array = Array.prototype.slice.call(arguments);
// const array = [...arguments];
const array = Array.from(arguments);

return array.reduce(function (pre, cur) {
return pre + cur;
}, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15
1
2
3
4
5
6
// Array.from에 length만 존재하는 유사 배열 객체를 전달하면 undefined를 요소로 채운다.

Array.from({ length: 3 }); // -> [undefined, undefined, undefined]
// Array.from은 두 번째 인수로 전달한 콜백 함수의 반환값으로 구성된 배열을 반환한다.

Array.from({ length: 3 }, (_, i) => i); // -> [0, 1, 2]

위 마지막 예에서 콜백함수 를 이용한 배열은 Array.from의 매개변수를 이용했다. MDN에 따르면, Array.from의 경우 Array.from(arrayLike[, mapFn[, thisArg]]) 구문 규칙을 따른다. 여기서 두번째 매개변수인 mapFn은 매핑함수이다.

즉, Array.from(obj, mapFn, thisArg)는 중간에 다른 배열을 생성하지 않는다는 점을 제외하면 Array.from(obj).map(mapFn, thisArg)와 같다.

1
2
3
4
5
6
7
const array1 = Array.from({ length: 3 });

// 매개변수 _ 는 명시적으로 비워둔다는 의미이다.

const map1 = array1.map((_, i) => i);

console.log(map1); // Array [0, 1, 2]

배열 고차 함수

고차 함수(Higher-Order Function, HOF)는 함수를 인수로 전달받거나 함수를 반환하는 함수를 말한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const arr = [1, 2, 3];

// 아래와 같은 순차로 순회하며 함수를 호출한다.
arr.map((v, i, arr) => {});

// 1: v = 1, i = 0, arr = [1, 2, 3]
// 2: v = 2, i = 1, arr = [1, 2, 3]
// 3: v = 3, i = 2, arr = [1, 2, 3]

const res = arr.map((v, i, arr) => {
return i;
});
console.log(res); // [0, 1, 2]

const res = arr.map((v, i, arr) => v ** v);
console.log(res); // [1, 4, 27]

Nyong’s GitHub