JS this

this는 객체 자신의 프로퍼티나 메소드를 참조하기 위한 자기 참조 변수(Self-referencing variable)이다. this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.

바인딩(Binding)
식별자와 값을 연결하는 과정. (ex. 변수는 할당에 의해 값에 바인딩)

  • this는 코드 어디든지 참조가 가능하다.
  • 객체의 프로퍼티나 메소드를 참조하기 위한 자기 참조 변수이므로 일반적으로 객체의 메소드 또는 생성자 함수에서 의미가 있다.
  • strict mode가 적용된 일반 함수 내부의 this에는 undefined가 바인딩된다.

함수 호출 방식과 this 바인딩

this 바인딩(가리키는 값)은 함수가 어떻게 호출되었는지에 따라 동적으로 결정됨.

함수 호출 방식 this 바인딩
일반 함수호출 전역객체
메소드 호출 메소드를 호출한 객체
생성자 함수 호출 생성자 함수가 (미래에) 생성할 인스턴스
Function.prototype.apply/call/bind 메소드에 의한 간접 호출 Function.prototype.apply/call/bind 메소드에 인자로 전달한 객체

일반 함수 호출

  • 기본적으로 this에는 전역 객체(Global object)가 바인딩된다.
  • 전역 함수 / 중첩 함수(메소드 내 정의한 중첩 함수 포함) / 콜백 함수를 일반 함수로 호출하면 함수 내부의 this에는 전역 객체가 바인딩된다.
  • 중첩 함수 또는 콜백 함수(보조 함수)는 외부 함수를 돕는 헬퍼 함수로서 역할하므로 외부 함수의 일부 로직을 대신하는 경우가 대부분이기 때문에 전역객체를 바인딩하게 되면 문제가 생긴다. 그러므로 메소드 내부의 중첩함수와 콜백 함수의 this 바인딩을 메소드의 this 바인딩과 일치시켜 주어야 한다.
1
2
3
4
5
6
7
8
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();

setTimeout 함수
두번째 매개변수에 전달한 시간(ms)만큼 대기한 다음, 첫번째 매개변수에 전달한 콜백 함수를 호출하는 타이머 함수

메소드 내부의 중첩 함수나 콜백 함수의 this 바인딩을 메소드의 this 바인딩과 일치시키기 위한 방법

1
2
3
4
5
6
7
8
9
10
11
12
var value = 1;
const obj = {
value: 50,
foo() {
const that = this;
setTimeout(function () {
console.log(that.value); // 50
}, 100);
}
};

obj.foo();

메소드 호출

  • 메소드 내부의 this는 메소드를 호출한 객체, 즉 메소드 이름 앞의 마침표(.) 연산자 앞에 기술한 객체에 바인딩된다.
  • 주의할 점: 메소드 내부의 this는 메소드를 소유한 객체가 아닌 메소드를 호출한 객체에 바인딩된다.
  • 프로토타입 메소드 내부에서 사용된 this도 일반 메소드와 마찬가지로 해당 메소드를 호출한 객체에 바인딩된다.
1
2
3
4
5
6
7
8
9
const person = {
name: 'Lee',
getName() {
name: 'Kim'
return this.name;
}
};

console.log(person.getName()); // 호출한 객체는 person

생성자 함수 호출

  • 생성자 함수 내부의 this에는 생성자 함수가 (미래에) 생성할 인스턴스가 바인딩된다.
  • 일반 함수와 동일한 방법으로 생성자 함수를 정의하고 new 연산자와 함께 호출하면 해당 함수는 생성자 함수로 동작한다.
  • new 연산자와 함께 생성자 함수를 호출하지 않으면 생성자 함수가 아니라 일반 함수로 동작한다.
1
2
3
4
5
6
7
8
9
10
11
12
function Circle(radius) {
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}

const circle1 = new Circle(5);
const circle2 = new Circle(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20

Function.prototype.apply/call/bind 메소드에 의한 간접 호출

  • this를 명시적으로 바인딩한다.
  • Function.prototype.apply, Function.prototype.call 메소드는 인수로 this와 인수 리스트를 전달받아 함수를 호출한다.
  • applycall 메소드의 본질적인 기능은 함수를 호출하는 것이다. 호출할 함수에 인수를 전달하는 방식만 다를 뿐 동일하게 동작한다.
    • apply 메소드: 호출할 함수의 인수를 배열로 묶어 전달.
    • call 메소드: 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달.
    • 대표적인 용도: arguments 객체와 같은 유사 배열 객체에 배열 메소드를 사용하는 경우.(arguements 객체는 배열이 아니기 때문에 Arry.prototype.slice와 같은 배열 메소드를 사용할 수 없다.)
    • Function 생성자 함수를 constructor 프로퍼티로 가리키는 모든 함수가 상속받아 사용할 수 있다.
  • bind 메소드는 this로 사용할 객체만을 전달한다.

apply, call 메소드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getThisBinding() {
console.log(arguments);
return this;
}

const thisArg = { a: 1 }; // this로 사용할 객체

console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// { a: 1 }

console.log(getThisBinding.call(thisArg, 1, 2, 3));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// { a: 1 }

bind 메소드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Person(name) {
this.name = name;
}

Person.prototype.doSomething = function (callback) {
callback.bind(this)();
// callback.apply(this);
// callback.call(this);
};

function foo() {
console.log(this.name);
}

const person = new Person('Lee');
person.doSomething(foo); // Lee

REFERENCE
https://poiemaweb.com

  • © 2020-2025 404 Not Found
  • Powered by Hexo Theme Ayer