Javascript에서 this란?
자바스크립트를 사용하면서 this에 대해 많이 헷갈렸습니다. 어떨 때는 this가 되고 어떤 함수에서는 this가 안되고 this가 어느 상황에서 어떤 것을 가르키는 것에 대해 잘 이해를 못하고 사용했습니다. 특히 저는 java를 많이 사용했었던 개발자로서 class 내의 this처럼 사용하려고 했습니다. this는 javascript에서 자주 사용되기도 하고 중요한 문법이기에 다시 한번 리마인드하면서 정리를 해보려고 합니다.
this란?
this
는 '자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수'다.this
를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메소드를 참조할 수 있다.
보통의 this 정의를 찾아보면 위와 같습니다. 정의를 살펴보면 중간에 또는
이라는 표현이 사용된 것을 볼 수 있습니다. 이는 this
가 고정된 값에 바인딩되지 않기 때문입니다. this
는 '함수가 호출되는 방식'에 따라서 동적으로 결정됩니다.
this 바인딩
this 바인딩을 통해 this가 어떤 값과 연결되는지 확인할 수 있습니다. 바인딩이랑 this
의 호출 방식에 따라 this
가 특정 '객체'에 연결되는 것입니다.
1. 전역 문맥에서는 모드 여부에 관계 없이 전역 객체 참조
console.log(this === window); //true
a = 30;
console.log(window.a); // 30
finction x() {
return this;
}
x() === window; //true
'use strict'
var x = this;
console.log(x === window); //true
전역 문맥에서 쓰이는 this
는 엄격 모드 여부와 관계 없이 전역 window 객체를 참조합니다.
2. 함수 내부의 this는 함수 호출 방법에 따라 다르다.
단순호출
엄격모드가 아닌 함수 안에서 this는 함수의 주인에게 바인딩됩니다.
function f1() {
return this;
}
// 브라우저
f1() === window; // true
// Node.js
f1() === global; // true
반면에 엄격 모드에서 함수 내의 this에 디폴트 바인딩이 없기 때문에 undefined가 됩니다.
"use strict";
function myFunction() {
return this;
}
console.log(myFunction()); //undefined
"use strict";
var num = 0;
function addNum() {
this.num = 100; //ERROR! Cannot set property 'num' of undefined
num++;
}
addNum();
3. 메서드 안에서 쓴 this
일반 함수가 아닌 메서드에서는 this
가 해당 메서드를 호출한 객체로 바인딩됩니다.
var person = {
firstName: 'John',
lastName: 'Doe',
fullName: function () {
return this.firstName + ' ' + this.lastName;
},
};
person.fullName(); //"John Doe"
var num = 0;
function showNum() {
console.log(this.num);
}
showNum(); //0
var obj = {
num: 200,
func: showNum,
};
obj.func(); //200
메서드 안의 함수 내부에서 this를 사용하면 전역 객체에 접근합니다.
var text = 'global';
var binding = {
text: 'local',
printText: function () {
console.log(this.text); // local
var innerFunc = function () {
console.log(this.text); // global
};
innerFunc();
}
};
binding.printText();
4. 이벤트 핸들러 안에서 쓴 this
이벤트 핸들러에서 this는 이벤트를 받는 HTML 요소를 가리킵니다.
var btn = document.querySelector('#btn')
btn.addEventListener('click', function () {
console.log(this); //#btn
});
5. 생성자 안에서 쓴 this
생성자 함수가 생성하는 객체로 this가 바인딩 됩니다.
function Person(name) {
this.name = name;
}
var kim = new Person('kim');
var lee = new Person('lee');
console.log(kim.name); //kim
console.log(lee.name); //lee
하지만 new 키워드를 빼먹는 순간 일반 함수 호출과 같아지기 때문에, 이 경우는 this가 window에 바인딩됩니다.
var name = 'window';
function Person(name) {
this.name = name;
}
var kim = Person('kim');
console.log(window.name); //kim
6. 명시적 바인딩
명시적 바인딩은 함수의 call, apply, bind 메소드를 사용해서 함수 내부에서 사용되는 this의 값이 어떤 값이 사용되야하는지 명확할 때 사용하는 방식입니다.
var name = "chris";
var age = 100;
function person(){
console.log("이름 : ", this.name);
console.log("나이 : ", this.age);
}
var mark = {
name : "mark",
age : 15
}
var tomas = {
name: "tomas",
age: 17
}
// 전역객체 this를 바인딩
person();
//call과 apply를 사용하여 person 내부에서 사용된 this의 값을 명시적으로 설정합니다.
person.call(mark);
person.apply(tomas);
//bind의 경우 함수를 직접 호출하지 않고 this가 명시적으로 설정된 함수를 반환합니다. 실행을 위해서는 반환받은 함수를 직접 실행해야합니다.
var tmp = person.bind(mark)
tmp();
//call vs apply
var age = 100;
function person(a,b,c,d,e){
console.log('age : ', this.age);
console.log('arguments : ', arguments);
}
var ken = {
age: 43
}
//call 함수의 경우 인자를 ,를 사용하여 여러개 받을 수 있습니다.
person.call(ken, 1,2,3,4);
person.call(ken, 1,2,3,4,5);
person.call(ken, 1,2,3,4,5,6);
//apply 함수의 경우 인자를 array 객체 하나만 받습니다.
person.apply(ken, [1,2,3,4]);
person.apply(ken, [1,2,3,4,5]);
person.apply(ken, [1,2,3,4,5,6]);
7. new를 통한 바인딩
function Foo() {
console.log(this);
}
new Foo(); // Foo
new를 통해 생성하게되면 this는 새로 생성된 객체를 가르킵니다.
8. 화살표 함수로 쓴 this
화살표 함수에서 this
는 자신을 감싼 정적 범위입니다. 화살표 함수는 전역 컨텍스트에서 실행되더라도 this
를 새로 정의하지 않고, 바로 바깥 함수나 클래스의 this
를 사용합니다.
var Person = function (name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(this); // Person {name: "Nana", age: 28}
setTimeout(function () {
console.log(this); // Window
console.log(this.name + ' is ' + this.age + ' years old');
}, 100);
};
};
var me = new Person('Nana', 28);
me.say(); //global is undefined years old
위 코드를 보면 내부 함수에서 this
가 전역 객체를 가리키는 바람에 의도와는 다른 결과가 나왔습니다.
var Person = function (name, age) {
this.name = name;
this.age = age;
this.say = function () {
console.log(this); // Person {name: "Nana", age: 28}
setTimeout(() => {
console.log(this); // Person {name: "Nana", age: 28}
console.log(this.name + ' is ' + this.age + ' years old');
}, 100);
};
};
var me = new Person('Nana', 28); //Nana is 28 years old
화살표 함수로 바꾸면 setTimeout을 감싼 함수의 this를 사용하기 때문에 person 객체를 가르키게 됩니다.
'프론트엔드 스터디 > Javascript' 카테고리의 다른 글
자바스크립트 실행 컨텍스트 (0) | 2021.07.12 |
---|---|
자바스크립트에서 scope란? (0) | 2021.07.12 |
Prototype이란? (0) | 2021.07.12 |
자바스크립트에서 함수란? (0) | 2021.07.09 |
strict mode(엄격모드)란? (0) | 2021.07.09 |