- 나이 : 96년생
- 특이사항 : MZ세대, INFJ, 오른손잡이, 아이폰 유저
- 좋아하는 음식 : 롯데리아, 솥뚜껑 삼겹살, BBQ 황금 올리브
- 취미 : 프로그래밍, 영화 보기
🥷기술
🐱 우리집 고양이 소개
- 이름 : 콜라
- 나이 : 14년생
- 종 : Nado moreum
📱 개인 프로젝트
🏢 참여한 프로젝트
🌱 내 잔디밭
자바스크립트는 this 를 알아야 됩니다. 본문
| 자바스크립트는 this 를 알아야 됩니다.
자바스크립트에서 this를 제대로 이해하지 못하면 클로저(Closure)를 활용하기 어렵고, 클로저를 활용하지 못한다면 일정 수준 이상의 코드를 작성하기 어렵게 됩니다. 물론 저는 더 좋은 코드를 주장하는 것 만큼 유치한건 없다고 생각하지만 적어도 언어에 대한 이해가 부족해서 좁혀진 방법으로 코드를 작성하는 것은 잘못되었다고 생각합니다. 앞으로 여러분들이 자바스크립트에서 this를 맞닥드리더라도 더이상 이것을 추상적으로 느끼시지 않았으면 합니다.
| 상황에 따라서 this 를 다르게 생각하기
저는 this 가 다르게 동작하는 네 가지 상황을 다음과 같이 나누고 각각에 대한 예시를 소개해드릴까 합니다.
| 메소드 안에서의 this
객체가 가지고 있는 함수를 메소드(Method) 라고 부릅니다. 여기서는 메소드가 사용되는 가장 일반적인 경우인 전역 함수를 먼저 살펴봅니다.
function beaver() {
console.log(this);
};
위와같이 전역 함수를 선언하면 그냥 함수가 허공에 만들어진다고 생각될 수 있겠지만 실제로는 전역 객체(window 혹은 global) 안에 함수가 선언되는 것이기 때문에 전역 함수도 결국에는 메소드 입니다. 이 beaver 함수를 호출해서 this가 무엇이 호출되었는지 확인해봅시다.
beaver();
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} //Chrome 콘솔에서 출력
전역 객체인 Window 가 출력됩니다. 이 결과로 메소드를 호출할 시 메소드 안에서 this는 함수를 소유하고 있는 객체가 된다는 것을 알 수 있습니다.
var beaver = {
foo : function() {
console.log(this);
}
}
beaver.foo(); // 여기서 this 는 beaver가 된다.
위와같이 사용자가 직접 객체 안에서 메소드를 만드는 경우에는 당연히 함수를 소유하고 있는 객체인 beaver 가 this가 됩니다.
| 메소드가 아닌 독립적인 함수 안에서의 this
항상 함수가 객체 안에서만 선언되는 것은 아닙니다. 즉, 언제나 메소드로만 함수가 선언되는것이 아니라는 말입니다. 예를들어 다음과 같이 함수 안에 함수가 선언되는 경우를 많이 볼 수 있습니다.
function beaver() {
function raccoon() {
console.log(this);
}
raccoon();
}
beaver(); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
beaver 전역 함수 안에 raccon 이라는 함수를 선언해 호출합니다. 이 경우 특정 객체에 함수를 선언한 것이 아닌 독립적인 함수로 선언되고 이런식으로 객체에 속해있지 않은 함수의 경우 this 는 전역객체가 됩니다.
| 생성자로 인해 호출된 this
function Beaver(name) {
this.name = name;
}
Beaver("foo");
console.log(window.name); // "foo"
위 함수에서의 this 는 전역객체가 되기 때문에 Baver 함수 호출 후 window의 name을 호출했을 때 "foo" 가 출력됨을 이제는 알고 있습니다.
그렇다면 함수를 new 연산자를 통해서 생성자로 호출하는 경우에도 this는 똑같이 전역 객체를 가리킬까요?
function Beaver(name) {
this.name = name;
}
var foo = new Beaver("foo"); // 이 생성자로 만들어진 객체 this 를 반환
var bar = new Beaver("bar"); // 이 생성자로 만들어진 객체 this 를 반환
console.log(window.name); // 빈 문자열 "" 이 출력
console.log(foo.name); // "foo"
console.log(bar.name); // "bar"
예상하셨겠지만 new 로 인해서 함수를 생성자로 호출하는 경우에는 함수 안에서 this가 새롭게 만들어진 객체를 가리키게 되고 위 코드에서 window.name 을 출력해도 빈 문자열이 출력됩니다. 여기서 눈치 빠른 분들은 알아채셨을 텐데 new 연산자로 호출한 함수 생성자는 반환할 때 자기 자신(this) 를 반환합니다. 그렇기 때문에 그 값을 각각 변수에 넣어 name 프로퍼티를 출력했을 때 해당 객체의 name에 접근할 수 있죠.
| 화살표 함수 안에서의 this
ES6 가 정의되면서 새롭게 추가된 화살표 함수(Arrow Function)의 경우 기존의 함수들과 다르게 this가 적용됩니다. 맞습니다. 개빡치지만 굉장히 단순하게 동작되기 때문에 몇가지 예시를 통해 금방 이해하실 수 있습니다.
var foo = () => {
console.log(this);
};
var beaver = {
foo : foo
};
foo(); // Window
beaver.foo(); //Window
원래대로 라면 메소드로 호출된 beaver.foo 함수의 결과는 함수를 소유하고있는 beaver가 this가 되어야 합니다. 하지만 화살표 함수는 함수를 호출하는 영역의 this 를 그대로 가져옵니다. 위 예제에서는 함수를 호출한 영역이 전역(즉, window) 객체이기 때문에 this 가 전역객체가 됩니다. 간단하죠?
| this 정해주기 (call, apply, bind)
언제나 this는 정해진 규칙에 의해서 작동하지만 규칙을 뒤로하고 함수를 호출할때 call 과 apply 함수를 이용해서 직접 this를 명시적으로 정해줄 수 있습니다.
function foo() {
console.log(this.name);
}
var beaver = {
name : "dorothy"
};
foo.call(beaver); // "dorothy"
위 예제에서 foo 함수를 호출하면 this 는 전역객체가 되어야 겠지만 call (혹은 apply) 를 이용해서 함수를 호출하게 되면 매개변수로 함수 안에서의 this를 지정할 수 있습니다. 기본적으로 call 과 apply 는 완전히 동일한 결과를 가지는 함수지만 사용하는 방법에서 차이가 있습니다.
function profile(age, weight) {
console.log(this.name);
console.log("age : " + age);
console.log("weight : " + weight);
}
var beaver = {
name : "dorothy"
};
profile.apply(beaver, [4, "2kg"]);
//profile.call(beaver, 4, "2kg");
위 예제에서 apply 와 call 을 호출한 부분을 살펴보면 apply 는 두번째 매개변수에 배열로 값을 묶어서 전달했지만 call 은 하나하나 값을 따로 전달해서 호출합니다. 즉, 함수를 호출할 때 매개변수로 전달할 값들을 배열로 묶어서 전달할지, 아니면 따로 하나하나 값을 넣어서 전달할지의 차이입니다.
function profile(age, weight) {
console.log(this.name);
console.log("age : " + age);
console.log("weight : " + weight);
}
var beaver = {
name : "dorothy"
};
profile.bind(beaver)(4, "2kg");
마지막으로 bind 를 사용해서도 this를 변경할 수 있음을 예제로 보여줍니다. 다만, bind의 경우 커링(currying) 에 대한 이해가 있어야 동작 방식을 이해하실 수 있습니다. 커링 기법은 여기서는 다루지 않습니다.
'글 묶음 > 사탄도 외면한 javascript' 카테고리의 다른 글
=== 쓰세요 (0) | 2019.03.25 |
---|---|
D3.js 쉽게 시작하세요 (10) | 2019.03.22 |
자바스크립트에서 || 은 참과 거짓을 판단하는 연산자가 아닙니다 (5) | 2019.02.14 |