자바스크립트에서 this
는 함수가 호출되는 방법에 따라 달라지는 특별한 키워드입니다. this
는 함수가 실행될 때 해당 함수가 소속된 객체를 참조합니다. 이 참조는 함수 호출 문맥(컨텍스트)에 따라 달라집니다. 즉, 함수를 어떻게 호출하느냐에 따라서 this
가 가리키는 대상이 달라진다는 뜻입니다.
객체.메서드명()
형식으로 호출합니다.함수명()
또는 변수명()
형식으로 호출합니다.this
키워드는 메서드 내에서 호출된 객체를 참조합니다. 메서드를 통해 객체의 속성과 메서드에 접근하고 변경할 수 있습니다.this
키워드는 일반적으로 함수 내에서 특별한 의미를 가지지 않습니다.strict mode
에서 실행되는 함수 내에서 this
는 undefined
를 참조합니다.strict mode
가 실행되지 않는 일반적인 함수에서 this
는 전역 객체를 참조합니다. 브라우저 환경에서 전역 객체는 window
객체입니다.JavaScript에서 this
의 값을 설정하는 네 가지 방법입니다.
동적 바인딩은 함수가 호출될 때 this
의 값이 결정되는 방식입니다. this
의 값은 함수가 어떻게 호출되는지에 따라 달라집니다.
전역에서의 this
는 전역 객체를 참조합니다.
console.log(this); // 브라우저에서는 window 객체, Node.js에서는 global 객체
window
객체는 웹 브라우저에서 JavaScript의 전역 객체로 사용되며, 웹 페이지에 관한 정보를 담고 있습니다. 또한, JavaScript의 내장 함수, 브라우저 제공 API, 그리고 사용자가 정의한 변수와 함수 등이 window
객체의 프로퍼티 혹은 메서드로 포함되어 있습니다.일반 함수 호출에서는 전역 객체를 참조합니다.
function showThis() {
console.log(this);
}
showThis(); // 브라우저에서는 window
엄격 모드에서는 undefined
를 참조합니다.
"use strict";
function showThis() {
console.log(this);
}
showThis(); // 엄격 모드에서는 undefined
객체의 메서드로 호출될 때 this
는 그 메서드를 소유한 객체를 참조합니다.
const person = {
name: 'jinwoo',
greet: function() {
console.log(this.name);
}
};
person.greet(); // 'jinwoo'
생성자 함수 내의 this
는 새로 생성된 객체를 참조합니다.
function Person(name) {
this.name = name;
}
const bob = new Person('Bob');
console.log(bob.name); // 'Bob'
명시적 바인딩은 함수의 this
값을 명시적으로 설정하는 방법입니다. call
, apply
, bind
메서드를 사용합니다.
call
call
메서드는 함수를 호출하면서 첫 번째 인자로 전달된 값을 this
로 설정합니다. 추가 인자는 함수의 매개변수로 전달됩니다.
function greet(greeting) {
console.log(`${greeting}, my name is ${this.name}`);
}
const user = { name: 'jinwoo' };
greet.call(user, 'Hello'); // Hello, my name is jinwoo
greet.call(user, 'Hello')
를 통해 greet()
함수를 호출하고 있습니다. 여기서 call
메서드의 첫 번째 전달인자로 user
객체를 전달하면, greet()
함수 내의 this
는 user
객체를 가리킵니다. 그래서 this.name
은 jinwoo
가 됩니다.call
메서드의 두 번째 인자로 "Hello"
문자열을 넘기면, 이 값은 greet()
함수의 첫 번째 인자 greeting
으로 전달됩니다. call
메서드 없이 함수를 호출하면, this
는 전역 객체를 참조합니다. call
메서드를 사용하지 않고 greet()
함수를 호출하면, this.name
은 전역 객체의 name
속성을 참조하는데, 전역에 name이 선언되어 있지 않다면, this.name
은 undefined
를 출력합니다.apply
apply
메서드는 call
과 비슷하지만, 함수의 매개변수를 배열로 전달받는 점이 다릅니다.
function greet(greeting, punctuation) {
console.log(`${greeting}, my name is ${this.name}${punctuation}`);
}
const user = { name: 'jinwoo' };
greet.apply(user, ['Hello', '!']); // Hello, my name is jinwoo!
greet.apply(user, ['Hello', '!'])
를 통해 greet()
를 호출하고 있습니다. apply
메서드의 첫 번째 인자로 user
객체를 전달하면, greet()
함수 내의 this
는 user
객체를 가리킵니다. 그래서 this.name
는 jinwoo
가 됩니다.apply
메서드의 두 번째 인자로 Hello
와 !
로 구성된 배열을 전달하면, greet()
함수의 첫 번째와 두 번째 매개변수로 전달됩니다.call
과 apply
메서드의 주요 목적call
과 apply
메서드의 주요 목적은 함수를 즉시 호출하면서 this
의 값을 특정 객체로 설정하는 것입니다. 이를 통해 함수 내부에서 this
가 참조하는 값을 직접 제어할 수 있습니다.
call
이나 apply
를 사용할 수 있습니다.let person1 = {
name: "jinwoo",
greet: function () {
console.log(`Hello, my name is ${this.name}`);
},
};
let person2 = {
name: "McDonald",
};
// person1의 greet 메서드를 person2의 컨텍스트에서 호출
person1.greet.call(person2); // "Hello, my name is McDonald"
call
메서드를 사용해서 person1
의 greet
메서드를 person2
의 컨텍스트에서 호출했습니다. 그래서 this.name
은 person2
의 name
를 참조하게 되어 Hello, my name is McDonald
를 출력합니다.bind
bind
메서드는 새로운 함수를 반환하며, 이 새로운 함수는 항상 주어진 this
값을 사용합니다. 원래 함수와 같은 인수를 받을 수 있습니다.
function greet(greeting) {
console.log(`${greeting}, my name is ${this.name}`);
}
const user = { name: 'jinwoo' };
const boundGreet = greet.bind(user);
boundGreet('Hello'); // Hello, my name is jinwoo
boundGreet
는 greet()
함수를 바인딩한 새로운 함수 입니다.greet.bind(user)
를 통해 greet()
함수를 호출하고 있는데, 여기서 bind
메서드는 새로운 함수를 반환합니다. greet()
함수와 같지만, this
가 user
객체를 가리키도록 고정됩니다. 그래서 boundGreet('Hello')
를 호출할 때, this.name
은 jinwoo
가 됩니다.bind
메서드의 주요 목적bind
메서드의 주요 목적은 함수의 this
값을 고정하는 것입니다.
this
는 기본적으로 함수가 호출되는 방식에 따라 그 값이 달라집니다. 이것을 동적 바인딩이라고 합니다. this
값이 특정 객체를 가리키도록 고정하고 싶다면, bind
메서드를 사용하면 됩니다.bind
메서드는 원래 함수와 동일한 함수를 반환하지만, this
값이 특정 객체를 가리키도록 고정된 상태입니다. 이렇게 반환된 함수를 호출하면, this
는 항상 bind
메서드에 전달된 객체를 가리킵니다.call
과 apply
메서드는 bind
와 비슷한 방식으로 this
를 명시적으로 지정할 수 있지만, this
를 고정하지는 않습니다. call
과 apply
는 함수를 즉시 호출하면서 this
값을 설정합니다. 그런데 bind
는 새로운 함수를 반환하며, 이 함수는 원래 함수와 동일하지만 this
값이 특정 객체를 가리키도록 고정되어 있습니다. 암시적 바인딩은 자바스크립트에서 함수가 호출될 때 this
가 암시적으로 설정되는 방식입니다. 객체의 메서드를 호출할 때 주로 발생하며, 메서드 호출 시점에 this
가 결정됩니다. 객체.메서드명()
형식으로 호출하는 형태를 의미합니다.
const person = {
name: 'jinwoo',
greet: function() {
console.log(this.name);
}
};
person.greet(); // 'jinwoo'
person.greet()
를 호출할 때, greet()
메서드 내의 this
는 그 메서드를 소유한 객체를 참조합니다.const person = {
name: 'Alice',
greet: function() {
console.log(this.name);
}
};
const greet = person.greet;
greet();
this
는 전역 객체를 참조합니다.this
는 person
객체를 가리키지 않고 전역 객체를 가리키게 됩니다.const person1 = {
name: 'Alice',
greet: function() {
console.log(this.name);
}
};
const person2 = {
name: 'Bob'
};
person2.greet = person1.greet;
person2.greet(); // 'Bob'
this
는 새로운 객체를 참조합니다.person.greet
메서드를 person2.greet
에 할당하고 호출하면 this
는 person2
객체를 가리키게 됩니다.const obj1 = {
name: 'obj1',
sayName() {
console.log(this.name);
},
};
const obj2 = {
name: 'obj2',
sayName: obj1.sayName,
}
obj2.sayName(); // obj2
obj2.sayName()
에서 obj2
의 sayName
프로퍼티는 obj1
의 sayName()
메서드를 참조하고 있습니다.obj2.sayName()
이 호출되는 시점에서 this
는 메서드를 호출한 객체 obj2
를 참조하게 됩니다. 그래서 this.name
는 obj2
의 name
값을 참조하게 됩니다. new
키워드는 생성자 함수를 호출할 때, 생성자 함수 내부의 this
는 새로 생성되는 객체를 가리킵니다.
function Person(name, age) {
// this는 새로 생성된 빈 객체를 참조합니다.
this.name = name;
this.age = age;
// 명시적인 반환이 없으므로 새로 생성된 객체가 반환됩니다.
}
// new 키워드를 사용하여 Person 객체를 생성합니다.
const person1 = new Person('jinwoo', 30);
console.log(person1); // Person { name: 'jinwoo', age: 30 }
console.log(person1.name); // jinwoo
console.log(person1.age); // 30
person1
변수는 new Person('Alice', 30)
을 통해 생성된 새 Person
객체를 참조합니다. Person
생성자 함수내의 this
는 새롭게 생성된 Person
객체를 가리킵니다. 그래서 person1
은 this
가 참조하는 Person
을 가리키게 됩니다.return
문이 없을 경우 undefined
를 반환합니다. 그런데 생성자 함수를 new
키워드를 사용하여 생성자 함수를 호출하면, 생성자 함수가 명시적으로 객체를 반환하지 않을 때 this
로 바인딩된 새로 생성된 객체가 반환됩니다.function Car(model) {
this.model = model;
}
Car.prototype.start = function () {
console.log(this.model + "가 출발합니다!");
};
const car1 = new Car("기아 K5");
const car2 = new Car("현대 싼타페");
car1.start(); // "기아 K5가 출발합니다!" 출력
car2.start(); // "현대 싼타페가 출발합니다!" 출력
// 생성된 객체는 생성자 함수의 프로토타입과 연결되어 프로토타입 체인을 통해 메서드와 프로퍼티를 상속받습니다.
prototype
은 기본적으로 공유 공간
으로 생각하면 됩니다. Car.prototype.start
는 Car
라는 공유 공간
에 start
라는 기능을 추가한 것 입니다. Car
로 만든 모든 객체들은 start
기능을 공유하게 됩니다. 즉 모든 Car
객체들은 start
를 사용해 시동
을 걸 수 있습니다.car1
과 car2
객체를 만들었을 때, 각각의 객체에 start
메서드를 따로 추가하지 않아도 start
메서드를 호출할 수 있습니다. 이렇게 Car.prototype.start
메서드는 Car
로 생성된 모든 객체가 공유하게 되는데, 이것이 prototype
의 역할입니다.this
는 함수가 호출되는 방식에 따라 다르게 결정되지만, 화살표 함수에서 this
는 항상 화살표 함수를 감싸는 외부 스코프에서 상속됩니다. 이것을 정적 바인딩(lexical binding) 이라고 합니다.const obj = {
name: 'Alice',
regularFunction: function() {
console.log(this.name); // 'Alice'
},
arrowFunction: () => {
console.log(this.name); // undefined (또는 브라우저 환경에서 'window.name'의 값)
}
};
obj.regularFunction(); // 'Alice'
obj.arrowFunction(); // undefined
regularFunction
은 호출된 객체 obj
를 this
로 참조하지만, arrowFunction
은 obj
가 아닌 상위 스코프(글로벌 스코프)의 this
를 참조합니다.this
가 함수를 선언한 시점의 this
를 바인딩하므로, obj
내부에서 선언된 화살표 함수에서 this
를 사용하더라도 obj
를 가리키지 않습니다. 따라서 this.name
은 Alice
가 아니라 undefined
가 됩니다.this
를 사용해 객체 자신의 속성이나 다른 메서드에 접근할 때는 일반 함수를 사용하는 것이 좋습니다. 일반 함수에서 this
는 함수를 호출한 객체를 가리킵니다. 그래서 메서드 내에서 this
를 통해 객체 자신의 속성이나 다른 메서드에 접근할 수 있습니다.// 일반 함수에서 this
const obj1 = {
name: "Alice",
sayHello: function() {
setTimeout(function() {
console.log(`Hello, ${this.name}`);
}, 1000);
}
};
obj1.sayHello(); // "Hello, undefined"
// 화살표 함수에서 this
const obj2 = {
name: "Alice",
sayHello: function() {
setTimeout(() => {
console.log(`Hello, ${this.name}`);
}, 1000);
}
};
obj2.sayHello(); // "Hello, Alice"
setTimeout
에서 사용된 콜백 함수는 일반 함수입니다. 일반 함수가 단독으로 호출되면 this
는 전역 객체를 가리킵니다.setTimeout
안의 함수가 화살표 함수이므로, this
는 sayHello
함수의 this
를 가리키게 됩니다. sayHello
함수는 obj2
객체의 메서드로 호출되었으므로, this
는 obj2
를 가리키게 됩니다. 따라서 this.name
은 'Alice'
가 됩니다.this
값을 바인딩한다는 것입니다. 이것을 정적 바인딩(lexical binding) 이라고 합니다. sayHello
함수 내부의 화살표 함수에서 this
는 sayHello
가 호출되는 시점의 this
를 가리키게 됩니다. 이 결과, this.name
은 'Alice'
를 출력하게 됩니다.let button = document.querySelector("button");
button.name = "MyButton";
button.addEventListener("click", () => {
console.log(this.name + " is clicked!");
});
this
는 버튼 요소를 가리킵니다. 클릭 이벤트가 발생하면 MyButton is clicked!
라는 메지가 출력됩니다.