this
일반적인 객체지향언어(C#, JAVA) 에서 this 는 특별한 처리가 없는한 항상 Class 본인을 가르킨다.
그러나 Javascript 에서 this 는 상당히 독특한 모습을 보여준다.
- this 가 가르키는 객체는 동적으로 변한다.
- 즉 호출 시점에 따라 this 는 변한다.
- 기본적으로 자바스크립트에서 this 는 window, global 을 가르킨다. ( strict mode 에선 undefined 할당 )
객체에서 this
- 일반 함수 호출방식의 this 는 전부 window ( 전역 객체 ) 를 가르킨다.
- 즉 어떤 함수라도 일반 함수로 호출되면 this 는 전역 객체
- 메소드 형태 ( 객체가 호출하는 ) 라면 this 가 호출한 객체에 바인드 된다.
const obj = {
name: "john",
// 메소드 형태 선언
foo() {
console.log(this); // obj
// 함수
function bar() {
console.log(this); // window
}
// 일반 함수 형태 호출
bar();
}
};
obj.foo();
일반 함수 호출 과 메소드의 차이?
일반 함수 호출은 함수형 언어에서 선언된 함수를 문자그대로 호출하는 방식 ex) add()
메소드는 객체 내부의 함수를 객채를 통하여 호출하는 경우 ex) calc.add();
따라서 아래와 같은 방법으로 this를 의도대로 동작하게 만든다.
일반 함수 this 일치
- this 객체를 잃지 않고 값에 담아 내부에서 사용할 수 있도록 한다.
const obj = {
name: "john",
foo(){
const _this = this;
console.log(this, "foo"); // obj
function bar(){
console.log(_this, "bar"); // obj
}
bar();
}
};
obj.foo();
명시적 바인드
- apply, call, bind 를 사용해서 this를 명시적으로 바인드 할 수 있다.
const obj = {
name: "john",
foo(){
setTimeout(function(){
console.log(this.name); // "john"
}.bind(this), 1000);
}
}
obj.foo();
화살표 함수
- 화살표 함수는 내부적으로 this를 가지고 있지 않다.
const obj = {
name: "john",
foo(){
setTimeout(() => {
console.log(this.name); // "john"
}, 1000);
}
}
obj.foo();
생성자 함수 this
- 생성자 함수 ( new ) 내부의 this 는 생성자 함수가 생성할 인스턴스에 바인딩 된다.
- new 연산자를 통해 새로운 객체를 생성하고 getName 함수는 프로토타입 체인 내부에 존재하기에
함수 호출시 name 을 가르킨다. - 하지만 직접 체인 내부에서 호출시 this 를 잃어버린다. 즉 호출한 객체에 따라 this는 변경된다. *
function Person (name) {
this.name = name;
}
Person.prototype.getName = function(){
console.log("getName 호출!");
return this.name;
};
const person = new Person("john");
console.log(person.getName()); // "john"
console.log(person.__proto__.getName()); // undefined
Person.prototype.name = "john2";
console.log(person.getName()); // "john"
console.log(person.__proto__.getName()); // "john2"
function Person (name) {
this.name = name;
// __proto__ 에서 생성되는것이 아닌 인스턴스 안에 직접 생성
this.getName = function () {
return this.name;
}
}
const person = new Person("john");
console.log(person.getName()); // "john"
const windowPerson = Person("john");
console.log(windowPerson);
// new 를 사용하지 않고 일반 함수로 사용시 내부 요소들이 window 속성으로 들어가 버린다.
Class 의 this
- class 내부에서 화살표 함수 this 는 생각과 다르게 호출객체를 가르키고 있다.
- 이는 클래스가 내부적으로 this를 명시적 바인딩 처리 하기 때문이다.
상세한 동작 원리에 대해서는 아직 지식이 부족하다. 예외적으로 외워두자.
class Person {
// static
static addr = "서울";
// Field 선언
age = 10;
// 인스턴스 선언
constructor(name){
this.name = name;
}
ageMethod(){
console.log(this.age, "Method");
}
ageField = function(){
console.log(this.age, "Field");
}
ageArrow = () => {
console.log(this.age, "arrow");
}
}
const person = new Person("john");
person.ageMethod(); // 10 "Method"
person.ageField(); // 10 "Field"
person.ageArrow(); // 10 "arrow"
const method = person.ageMethod;
method(); // expected error, Cannot read properties of undefined (reading 'age')
const field = person.ageField;
field(); // expected error, Cannot read properties of undefined (reading 'age')
const arrow = person.ageArrow;
arrow(); // 10 "arrow"
DOM
- 이벤트 리스너 내부 콜백 함수의 this 는 DOM 객체 를 가르킨다.
<body>
<button class="btn">버튼</button>
<script>
const $btn = document.querySelector(".btn");
$btn.addEventListener("click", function (evt) {
console.log("target", e.target); // <button class="btn">버튼</button>
console.log("function", this); // <button class="btn">버튼</button>
});
$btn.addEventListener("click", (evt) => {
console.log("arrow", this); // Window
});
</script>
</body>
<body>
<button class="btn">버튼</button>
<script>
const $btn = document.querySelector(".btn");
$btn.onclick = function (evt) {
console.log(this); // <button class="btn">버튼</button>
};
</script>
</body>
<body>
<button class="btn" onclick="onClick(this, event)">버튼</button>
<script>
function onClick(_this, event) {
console.log(this); // Window
console.log(_this); // <button class="btn" onclick="onClick(this)">버튼</button>
console.log(event); // Event
}
</script>
</body>
apply, call, bind
- call, apply 의 본질적인 기능은 함수를 호출하는 것 이다.
- bind 는 함수를 호출 하지 않는다.
function thisFunc ( age ) {
this.age = age
return this;
}
const obj = {name: "dj"};
console.log(thisFunc(26)); // window
console.log(thisFunc.call(obj, 26));
console.log(thisFunc.apply(obj, [26]));
function thisFunc ( age ) {
this.age = age
return this;
}
const obj = {name: "dj"};
console.log(thisFunc(26)); // window
thisFunc.bind(obj); // 호출되지 않는다. 따라서 할당을 하거나 즉시 실행해야한다.
// thisFunc.bind(obj)();
thisFunc = thisFunc.bind(obj); // this 가 명시적으로 지정된 함수로 변경
console.log(thisFunc(27)); // obj
There might be incorrect information or outdated content.
'Web > Javascript' 카테고리의 다른 글
[JAVASCRIPT] for~in vs for~of (0) | 2023.08.28 |
---|---|
[JAVASCRIPT] try-catch 에러 전파 (0) | 2023.08.15 |
[JAVASCRIPT] isNaN 검사 (0) | 2023.08.15 |
[JAVASCRIPT] DOM - 노드 조작 (0) | 2023.08.04 |
[JAVASCRIPT] DOM - 노드 탐색 (0) | 2023.08.04 |