call()
call()메소드를 MDN에서는 이렇게 정의하고 있다. '주어진 this값 및 각각 전달된 인수와 함께 함수를 호출한다.' call은 이미 할당되어있는 다른 객체의 함수, 메소드를 호출하는 해당 객체에 재할당할때 사용된다. 또한 메소드를 한번 작성하면 새 객체를 위한 메소드를 재작성할 필요 없이 call()을 이용해 다른 객체에 상속할 수 있다.
function getName() {
console.log(`movie's name is ${this.name}`);
}
const movie = {
name: 'LaLaLand',
actor: 'Ryan Gosling'
}
위와 같은 코드가 있을 때, movie객체에서 name을 출력하는 메소드가 필요하다고 하자. 일단 getName함수가 movie객체 안에 있지 않기 때문에 movie.getName()과 같이 호출을 할 수 없다. 이때, call()을 이용해 movie객체에 getName함수를 상속시킬 수 있다.
getName.call(movie); // movie's name is LaLaLand
위와 같이 getName을 호출하면 this가 movie에 바인딩 된다. 이때, call()메소드의 첫 번째 인자에 아무런 값도 주지 않게 되면 this는 전역 객체에 바인딩된다.
let name = 'WhiPlash';
function getName() {
console.log(`movie's name is ${this.name}`);
}
const movie = {
name: 'LaLaLand',
actor: 'Ryan Gosling'
}
getName.call(); // movie's name is WhiPlash
apply()
MDN에서는 apply()메소드를 다음과 같이 정의한다. '주어진 this 값과 배열로 제공되는 arguments 로 함수를 호출한다.' apply()는 call()메소드와 거의 동일하지만 한 가지 차이점이 있다. call()이 함수의 인자들을 하나씩 받는 반면, apply()는 하나의 배열을 받는다. 또한 call()과 마찬가지로 이미 존재하는 함수를 호출할 때 다른 this객체를 할당할 수 있으며 새로운 객체마다 메소드를 재작성할 필요없이 한 번만 작성해 다른 객체에 상속시킬 수 있다.
function getName(m1, m2, m3) {
console.log(`His name is ${this.director}. He directed ${m1}, ${m2} and ${m3}`);
}
const movie = {
name: 'LaLaLand',
actor: 'Ryan Gosling',
director: 'Damien Chazelle'
}
movies = ['LaLaLand', 'WhiPlash', 'FirstMan'];
getName.apply(movie, movies); // His name is Damien Chazelle. He directed LaLaLand, WhiPlash and FirstMan
위와 같이 this가 바인딩될 객체인 movie와 getName의 파라미터인 m1, m2, m3에 해당하는 단일 배열 movies을 넘겨준다. apply()역시 첫 번째 인자가 null일 경우, 전역 객체를 가리킨다. 위의 예에서 call()의 경우 다음과 같이 사용할 수 있다.
getName.call(movie, movies[0], movies[1], movies[2]);
bind()
bind()메소드의 정의는 다음과 같다. 'bind()메소드가 호출되면 새로운 함수를 생성합니다. 받게되는 첫 인자의 value로는 this 키워드를 설정하고, 이어지는 인자들은 바인드된 함수의 인수에 제공된다.' 정의에서 나와 있듯이 bind()는 새로운 함수를 생성한다. call()과 apply()와 같이 첫 번째 인자로 this가 바인딩될 객체를 넘겨준다.
function getName(m1, m2, m3) {
console.log(`His name is ${this.director}. He directed ${m1}, ${m2} and ${m3}`);
}
const movie = {
name: 'LaLaLand',
actor: 'Ryan Gosling',
director: 'Damien Chazelle'
}
movies = ['LaLaLand', 'WhiPlash', 'FirstMan'];
const myFunction = getName.bind(movie, movies[0], movies[1], movies[2]);
myFunction(); // His name is Damien Chazelle. He directed LaLaLand, WhiPlash and FirstMan
앞서 설명한바와 같이, bind()는 새로운 함수를 생성하기 때문에 위와 같이 myFunction에 담아 나중에 호출할 수 있다. MDN의 예시를 하나 살펴보자.
this.x = 9;
let module = {
x: 81,
getX: function() { console.log(this.x); }
};
module.getX(); // 81
let retrieveX = module.getX;
retrieveX(); // 9
let boundGetX = retrieveX.bind(module);
boundGetX(); // 81
첫 번째로, module.getX()는 암시적 바인딩으로 getX의 this가 module에 바인딩된다. 따라서 81이 출력되는 것을 볼 수 있다. 두 번째 예로는 module객체의 getX메소드를 추출하여 retrieveX에 담고, 전역 스코프에서 retrieveX()와 같이 호출을 하였다. 이렇게 되면 일반 함수를 호출한것과 같이 this가 전역 객체를 가리키게 되므로 9를 출력한다. 세 번째는 추출한 함수에 module을 인자로 주고 명시적 바인딩을 했으므로 this는 module에 바인딩 된다. 따라서 module의 x값이 출력이 되는 것을 볼 수 있다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 부분 문자열 추출하는 방법 (0) | 2020.10.27 |
---|---|
[JavaScript] ECMAScript, JavaScript, es2015, ES6의 차이 (0) | 2020.08.15 |
[JavaScript] 'this'의 이해 (0) | 2020.08.07 |
[JavaScript] 클로저(Closure)란? (0) | 2020.07.30 |
[JavaScript] Scope(스코프) 이해하기 (0) | 2020.07.25 |