[Medium] ๐ this Binding
1. What is this in JavaScript?โ
JavaScript์์
this๋ ๋ฌด์์ธ๊ฐ์?
this๋ JavaScript์ ํค์๋๋ก, ํจ์๊ฐ ์คํ๋ ๋์ ์ปจํ
์คํธ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. this์ ๊ฐ์ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋๋์ง์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ฉฐ, ์ด๋์์ ์ ์๋์๋์ง์๋ ๊ด๋ จ์ด ์์ต๋๋ค.
this์ ๋ฐ์ธ๋ฉ ๊ท์นโ
JavaScript์์ this์ ๋ฐ์ธ๋ฉ์๋ ๋ค ๊ฐ์ง ๊ท์น์ด ์์ต๋๋ค(์ฐ์ ์์ ๋์ ์):
- new ๋ฐ์ธ๋ฉ:
newํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ์ ํจ์๋ฅผ ํธ์ถ - ๋ช
์์ ๋ฐ์ธ๋ฉ:
call,apply,bind๋ฅผ ์ฌ์ฉํ์ฌthis๋ฅผ ๋ช ์์ ์ผ๋ก ์ง์ - ์์์ ๋ฐ์ธ๋ฉ: ๊ฐ์ฒด ๋ฉ์๋๋ก ํธ์ถ
- ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ: ๊ธฐํ ์ํฉ์์์ ๊ธฐ๋ณธ ๋์
2. Please explain the difference of this in different contextsโ
์๋ก ๋ค๋ฅธ ์ปจํ ์คํธ์์
this์ ์ฐจ์ด๋ฅผ ์ค๋ช ํด ์ฃผ์ธ์
1. ์ ์ญ ํ๊ฒฝ์์์ thisโ
console.log(this); // ๋ธ๋ผ์ฐ์ : window, Node.js: global
function globalFunction() {
console.log(this); // ๋น์๊ฒฉ ๋ชจ๋: window/global, ์๊ฒฉ ๋ชจ๋: undefined
}
globalFunction();
'use strict';
function strictFunction() {
console.log(this); // undefined
}
strictFunction();
2. ์ผ๋ฐ ํจ์(Function)์์์ thisโ
์ผ๋ฐ ํจ์์ this๋ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ ๊ฒฐ์ ๋ฉ๋๋ค:
function regularFunction() {
console.log(this);
}
// ์ง์ ํธ์ถ: this๋ ์ ์ญ ๊ฐ์ฒด(๋น์๊ฒฉ ๋ชจ๋) ๋๋ undefined(์๊ฒฉ ๋ชจ๋)๋ฅผ ๊ฐ๋ฆฌํด
regularFunction(); // window (๋น์๊ฒฉ ๋ชจ๋) ๋๋ undefined (์๊ฒฉ ๋ชจ๋)
// ๊ฐ์ฒด ๋ฉ์๋๋ก ํธ์ถ: this๋ ํด๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํด
const obj = {
method: regularFunction,
};
obj.method(); // obj
// call/apply/bind ์ฌ์ฉ: this๋ ์ง์ ๋ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํด
const customObj = { name: 'Custom' };
regularFunction.call(customObj); // customObj
3. ํ์ดํ ํจ์(Arrow Function)์์์ thisโ
ํ์ดํ ํจ์๋ ์์ฒด this๋ฅผ ๊ฐ์ง์ง ์์ผ๋ฉฐ, ์ธ๋ถ ์ค์ฝํ์ this๋ฅผ ์์ํฉ๋๋ค(๋ ์์ปฌ ์ค์ฝํ).
const obj = {
name: 'Object',
// ์ผ๋ฐ ํจ์
regularMethod: function () {
console.log('regularMethod this:', this); // obj
// ๋ด๋ถ ์ผ๋ฐ ํจ์: this๊ฐ ๋ณ๊ฒฝ๋จ
function innerRegular() {
console.log('innerRegular this:', this); // window/undefined
}
innerRegular();
// ๋ด๋ถ ํ์ดํ ํจ์: this๋ ์ธ๋ถ์์ ์์
const innerArrow = () => {
console.log('innerArrow this:', this); // obj
};
innerArrow();
},
// ํ์ดํ ํจ์
arrowMethod: () => {
console.log('arrowMethod this:', this); // window(์ ์ญ์์ ์์)
},
};
obj.regularMethod();
obj.arrowMethod();
4. ๊ฐ์ฒด ๋ฉ์๋์์์ thisโ
const person = {
name: 'John',
age: 30,
// ์ผ๋ฐ ํจ์: this๋ person์ ๊ฐ๋ฆฌํด
greet: function () {
console.log(`Hello, I'm ${this.name}`); // "Hello, I'm John"
},
// ES6 ์ถ์ฝ ๋ฉ์๋: this๋ person์ ๊ฐ๋ฆฌํด
introduce() {
console.log(`I'm ${this.name}, ${this.age} years old`);
},
// ํ์ดํ ํจ์: this๋ ์ธ๋ถ(์ฌ๊ธฐ์๋ ์ ์ญ)์์ ์์
arrowGreet: () => {
console.log(`Hello, I'm ${this.name}`); // "Hello, I'm undefined"
},
};
person.greet(); // "Hello, I'm John"
person.introduce(); // "I'm John, 30 years old"
person.arrowGreet(); // "Hello, I'm undefined"
5. ์์ฑ์ ํจ์์์์ thisโ
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function () {
console.log(`Hello, I'm ${this.name}`);
};
}
const john = new Person('John', 30);
john.greet(); // "Hello, I'm John"
console.log(john.name); // "John"
6. Class์์์ thisโ
class Person {
constructor(name) {
this.name = name;
}
// ์ผ๋ฐ ๋ฉ์๋: this๋ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํด
greet() {
console.log(`Hello, I'm ${this.name}`);
}
// ํ์ดํ ํจ์ ์์ฑ: this๋ ์ธ์คํด์ค์ ๋ฐ์ธ๋ฉ๋จ
arrowGreet = () => {
console.log(`Hi, I'm ${this.name}`);
};
}
const john = new Person('John');
john.greet(); // "Hello, I'm John"
// ๋ฉ์๋๋ฅผ ๋ณ์์ ํ ๋นํ๋ฉด this ๋ฐ์ธ๋ฉ์ด ์ฌ๋ผ์ง
const greet = john.greet;
greet(); // ์ค๋ฅ: Cannot read property 'name' of undefined
// ํ์ดํ ํจ์ ์์ฑ์ this ๋ฐ์ธ๋ฉ์ ์์ง ์์
const arrowGreet = john.arrowGreet;
arrowGreet(); // "Hi, I'm John"
3. Quiz: What will be printed?โ
ํด์ฆ: ๋ค์ ์ฝ๋๋ ๋ฌด์์ ์ถ๋ ฅํ ๊น์?
๋ฌธ์ 1: ๊ฐ์ฒด ๋ฉ์๋์ ํ์ดํ ํจ์โ
const obj = {
name: 'Object',
regularFunc: function () {
console.log('A:', this.name);
},
arrowFunc: () => {
console.log('B:', this.name);
},
};
obj.regularFunc();
obj.arrowFunc();
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// A: Object
// B: undefined
์ค๋ช :
regularFunc๋ ์ผ๋ฐ ํจ์๋ก,obj.regularFunc()๋ก ํธ์ถ๋๋ฏ๋กthis๋obj๋ฅผ ๊ฐ๋ฆฌํค๋ฉฐ,"A: Object"๊ฐ ์ถ๋ ฅ๋ฉ๋๋คarrowFunc๋ ํ์ดํ ํจ์๋ก, ์์ฒดthis๊ฐ ์๊ณ ์ธ๋ถ(์ ์ญ)์this๋ฅผ ์์ํฉ๋๋ค. ์ ์ญ์name์์ฑ์ด ์์ผ๋ฏ๋ก"B: undefined"๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค
๋ฌธ์ 2: ํจ์๋ฅผ ์ธ์๋ก ์ ๋ฌโ
const person = {
name: 'John',
greet: function () {
console.log(`Hello, ${this.name}`);
},
};
person.greet(); // 1
const greet = person.greet;
greet(); // 2
setTimeout(person.greet, 1000); // 3
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// 1: "Hello, John"
// 2: "Hello, undefined" ๋๋ ์ค๋ฅ(์๊ฒฉ ๋ชจ๋)
// 3: "Hello, undefined" ๋๋ ์ค๋ฅ(์๊ฒฉ ๋ชจ๋)
์ค๋ช :
person.greet()- ๊ฐ์ฒด๋ฅผ ํตํด ํธ์ถํ๋ฏ๋กthis๋person์ ๊ฐ๋ฆฌํดgreet()- ๋ฉ์๋๋ฅผ ๋ณ์์ ํ ๋นํ ํ ์ง์ ํธ์ถํ๋ฉดthis๊ฐ ์ฌ๋ผ์ง๊ณ , ์ ์ญ ๋๋undefined๋ฅผ ๊ฐ๋ฆฌํดsetTimeout(person.greet, 1000)- ๋ฉ์๋๊ฐ ์ฝ๋ฐฑ ํจ์๋ก ์ ๋ฌ๋์ดthis๊ฐ ์ฌ๋ผ์ง
๋ฌธ์ 3: ์ค์ฒฉ ํจ์โ
const obj = {
name: 'Outer',
method: function () {
console.log('A:', this.name);
function inner() {
console.log('B:', this.name);
}
inner();
const arrow = () => {
console.log('C:', this.name);
};
arrow();
},
};
obj.method();
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// A: Outer
// B: undefined
// C: Outer
์ค๋ช :
A-method๊ฐobj๋ฅผ ํตํด ํธ์ถ๋๋ฏ๋กthis๋obj๋ฅผ ๊ฐ๋ฆฌํดB-inner๋ ์ผ๋ฐ ํจ์๋ก ์ง์ ํธ์ถ๋๋ฏ๋กthis๋ ์ ์ญ ๋๋undefined๋ฅผ ๊ฐ๋ฆฌํดC-arrow๋ ํ์ดํ ํจ์๋ก ์ธ๋ถmethod์this๋ฅผ ์์ํ์ฌobj๋ฅผ ๊ฐ๋ฆฌํด
๋ฌธ์ 4: setTimeout๊ณผ ํ์ดํ ํจ์โ
const obj = {
name: 'Object',
method1: function () {
setTimeout(function () {
console.log('A:', this.name);
}, 100);
},
method2: function () {
setTimeout(() => {
console.log('B:', this.name);
}, 100);
},
};
obj.method1();
obj.method2();
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// A: undefined
// B: Object
์ค๋ช :
A-setTimeout์ ์ฝ๋ฐฑ์ด ์ผ๋ฐ ํจ์์ด๋ฏ๋ก, ์คํ ์this๋ ์ ์ญ์ ๊ฐ๋ฆฌํดB-setTimeout์ ์ฝ๋ฐฑ์ด ํ์ดํ ํจ์์ด๋ฏ๋ก, ์ธ๋ถmethod2์this๋ฅผ ์์ํ์ฌobj๋ฅผ ๊ฐ๋ฆฌํด
๋ฌธ์ 5: ๋ณต์กํ this ๋ฐ์ธ๋ฉโ
const obj1 = {
name: 'obj1',
getThis: function () {
return this;
},
};
const obj2 = {
name: 'obj2',
};
console.log('A:', obj1.getThis().name);
const getThis = obj1.getThis;
console.log('B:', getThis() === window); // ๋ธ๋ผ์ฐ์ ํ๊ฒฝ ๊ฐ์
obj2.getThis = obj1.getThis;
console.log('C:', obj2.getThis().name);
const boundGetThis = obj1.getThis.bind(obj2);
console.log('D:', boundGetThis().name);
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// A: obj1
// B: true
// C: obj2
// D: obj2
์ค๋ช :
A-obj1์ ํตํด ํธ์ถํ๋ฏ๋กthis๋obj1์ ๊ฐ๋ฆฌํดB- ์ง์ ํธ์ถํ๋ฏ๋กthis๋ ์ ์ญ(window)์ ๊ฐ๋ฆฌํดC-obj2๋ฅผ ํตํด ํธ์ถํ๋ฏ๋กthis๋obj2๋ฅผ ๊ฐ๋ฆฌํดD-bind๋ฅผ ์ฌ์ฉํ์ฌthis๋ฅผobj2๋ก ๋ฐ์ธ๋ฉ
๋ฌธ์ 6: ์์ฑ์ ํจ์์ ํ๋กํ ํ์ โ
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
console.log(`Hello, I'm ${this.name}`);
};
Person.prototype.delayedGreet = function () {
setTimeout(function () {
console.log('A:', this.name);
}, 100);
};
Person.prototype.arrowDelayedGreet = function () {
setTimeout(() => {
console.log('B:', this.name);
}, 100);
};
const john = new Person('John');
john.delayedGreet();
john.arrowDelayedGreet();
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// A: undefined
// B: John
์ค๋ช :
A-setTimeout์ ์ผ๋ฐ ํจ์ ์ฝ๋ฐฑ์ผ๋ก,this๋ ์ ์ญ์ ๊ฐ๋ฆฌํดB-setTimeout์ ํ์ดํ ํจ์ ์ฝ๋ฐฑ์ผ๋ก, ์ธ๋ถarrowDelayedGreet์this๋ฅผ ์์ํ์ฌjohn์ ๊ฐ๋ฆฌํด
๋ฌธ์ 7: ์ ์ญ ๋ณ์ vs ๊ฐ์ฒด ์์ฑโ
var name = 'jjjj';
var obj = {
a: function () {
name = 'john';
console.log(this.name);
},
};
obj.a();
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// undefined
์ค๋ช :
์ด ๋ฌธ์ ์ ํต์ฌ์ ์ ์ญ ๋ณ์์ ๊ฐ์ฒด ์์ฑ์ ์ฐจ์ด๋ฅผ ์ดํดํ๋ ๊ฒ์ ๋๋ค:
-
obj.a()์this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฒ:obj.a()๋ก ํธ์ถํ๋ฏ๋กthis๋obj๋ฅผ ๊ฐ๋ฆฌํด
-
name = 'john'์ ์ ์ญ ๋ณ์๋ฅผ ์์ ํจ:name = 'john'; // var/let/const ์์ด, ์ ์ญ name์ ์์ // ๋ค์๊ณผ ๋์ผwindow.name = 'john'; // ๋ธ๋ผ์ฐ์ ํ๊ฒฝ -
this.name์ ๊ฐ์ฒด ์์ฑ์ ์ ๊ทผํจ:console.log(this.name); // console.log(obj.name)๊ณผ ๋์ผ -
obj๊ฐ์ฒด์๋name์์ฑ์ด ์์:obj.name; // undefined(obj ๊ฐ์ฒด ๋ด์ name์ด ์ ์๋์ง ์์)
์ ์ฒด ์คํ ๊ณผ์ :
// ์ด๊ธฐ ์ํ
window.name = 'jjjj'; // ์ ์ญ ๋ณ์
obj = {
a: function () { /* ... */ },
// ์ฃผ์: obj์๋ name ์์ฑ์ด ์์!
};
// obj.a() ์คํ
obj.a();
โ
// 1. name = 'john' โ ์ ์ญ window.name ์์
window.name = 'john'; // โ
์ ์ญ ๋ณ์๊ฐ ์์ ๋จ
// 2. this.name โ obj.name์ ์ ๊ทผ
this.name; // obj.name๊ณผ ๋์ผ
obj.name; // undefined(obj์ name ์์ฑ์ด ์์)
ํํ ์คํด:
๋ง์ ์ฌ๋๋ค์ด 'john'์ด ์ถ๋ ฅ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋๋ฐ, ์ด๋:
- โ
name = 'john'์ดobj์ ์์ฑ์ ์ถ๊ฐํ๋ค๊ณ ์คํด - โ
this.name์ด ์ ์ญ ๋ณ์์ ์ ๊ทผํ๋ค๊ณ ์คํด
์ฌ๋ฐ๋ฅธ ์ดํด:
- โ
name = 'john'์ ์ ์ญ ๋ณ์๋ง ์์ ํ๋ฉฐobj์๋ ์ํฅ์ ์ฃผ์ง ์์ - โ
this.name์ด ์ ๊ทผํ๋ ๊ฒ์obj.name์ด์ง, ์ ์ญname์ด ์๋
'john'์ ์ถ๋ ฅํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์์ฑํด์ผ ํฉ๋๋ค:
var obj = {
a: function () {
this.name = 'john'; // โ
obj์ name ์์ฑ ์ถ๊ฐ
console.log(this.name); // 'john'
},
};
obj.a(); // 'john' ์ถ๋ ฅ
console.log(obj.name); // 'john'
๋ฌธ์ 8: ์ ์ญ ๋ณ์ ํจ์ (์ฌํ)โ
var name = 'global';
var obj = {
name: 'object',
a: function () {
name = 'modified'; // ์ฃผ์: var/let/const ์์
console.log('1:', name); // ์ ์ญ ๋ณ์์ ์ ๊ทผ
console.log('2:', this.name); // ๊ฐ์ฒด ์์ฑ์ ์ ๊ทผ
},
};
obj.a();
console.log('3:', name); // ์ ์ญ ๋ณ์
console.log('4:', obj.name); // ๊ฐ์ฒด ์์ฑ
ํด๋ฆญํ์ฌ ์ ๋ต ๋ณด๊ธฐ
// 1: modified
// 2: object
// 3: modified
// 4: object
์ค๋ช :
// ์ด๊ธฐ ์ํ
window.name = 'global'; // ์ ์ญ ๋ณ์
obj.name = 'object'; // ๊ฐ์ฒด ์์ฑ
// obj.a() ์คํ
name = 'modified'; // ์ ์ญ window.name ์์
console.log('1:', name); // ์ ์ญ ์ ๊ทผ: 'modified'
console.log('2:', this.name); // obj.name ์ ๊ทผ: 'object'
// ์คํ ์๋ฃ ํ
console.log('3:', name); // ์ ์ญ: 'modified'
console.log('4:', obj.name); // ๊ฐ์ฒด: 'object'(์์ ๋์ง ์์)
ํต์ฌ ๊ฐ๋ :
name(this.์์ด) โ ์ ์ญ ๋ณ์์ ์ ๊ทผthis.name(this.์์) โ ๊ฐ์ฒด ์์ฑ์ ์ ๊ทผ- ์ด ๋์ ์์ ํ ๋ค๋ฅธ ๋ณ์์ ๋๋ค!
4. How to preserve this in callbacks?โ
์ฝ๋ฐฑ ํจ์์์
this๋ฅผ ์ ์งํ๋ ๋ฐฉ๋ฒ์?
๋ฐฉ๋ฒ 1: ํ์ดํ ํจ์ ์ฌ์ฉโ
const obj = {
name: 'Object',
method: function () {
// โ
ํ์ดํ ํจ์๋ ์ธ๋ถ์ this๋ฅผ ์์ํจ
setTimeout(() => {
console.log(this.name); // "Object"
}, 1000);
},
};
obj.method();
๋ฐฉ๋ฒ 2: bind() ์ฌ์ฉโ
const obj = {
name: 'Object',
method: function () {
// โ
bind๋ก this ๋ฐ์ธ๋ฉ
setTimeout(
function () {
console.log(this.name); // "Object"
}.bind(this),
1000
);
},
};
obj.method();
๋ฐฉ๋ฒ 3: this๋ฅผ ๋ณ์์ ์ ์ฅ(์ด์ ๋ฐฉ๋ฒ)โ
const obj = {
name: 'Object',
method: function () {
// โ
this๋ฅผ ๋ณ์์ ์ ์ฅ
const self = this;
setTimeout(function () {
console.log(self.name); // "Object"
}, 1000);
},
};
obj.method();
๋ฐฉ๋ฒ 4: call() ๋๋ apply() ์ฌ์ฉโ
function greet() {
console.log(`Hello, I'm ${this.name}`);
}
const person1 = { name: 'John' };
const person2 = { name: 'Jane' };
greet.call(person1); // "Hello, I'm John"
greet.apply(person2); // "Hello, I'm Jane"
5. Common this pitfallsโ
ํํ
thisํจ์
ํจ์ 1: ๊ฐ์ฒด ๋ฉ์๋๋ฅผ ๋ณ์์ ํ ๋นโ
const obj = {
name: 'Object',
greet: function () {
console.log(this.name);
},
};
obj.greet(); // โ
"Object"
const greet = obj.greet;
greet(); // โ undefined(this๊ฐ ์ฌ๋ผ์ง)
// ํด๊ฒฐ ๋ฐฉ๋ฒ: bind ์ฌ์ฉ
const boundGreet = obj.greet.bind(obj);
boundGreet(); // โ
"Object"
ํจ์ 2: ์ด๋ฒคํธ ๋ฆฌ์ค๋์์์ thisโ
const button = document.querySelector('button');
const obj = {
name: 'Object',
// โ ํ์ดํ ํจ์: this๊ฐ button์ ๊ฐ๋ฆฌํค์ง ์์
handleClick1: () => {
console.log(this); // window
},
// โ
์ผ๋ฐ ํจ์: this๋ ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ ์์๋ฅผ ๊ฐ๋ฆฌํด
handleClick2: function () {
console.log(this); // button ์์
},
// โ
๊ฐ์ฒด์ this์ ์ ๊ทผํด์ผ ํ๋ ๊ฒฝ์ฐ ํ์ดํ ํจ์๋ก ๋ํ
handleClick3: function () {
button.addEventListener('click', () => {
console.log(this.name); // "Object"
});
},
};
ํจ์ 3: ๋ฐฐ์ด ๋ฉ์๋์ ์ฝ๋ฐฑโ
const obj = {
name: 'Object',
items: [1, 2, 3],
// โ ์ผ๋ฐ ํจ์ ์ฝ๋ฐฑ์ this๋ฅผ ์์
processItems1: function () {
this.items.forEach(function (item) {
console.log(this.name, item); // undefined 1, undefined 2, undefined 3
});
},
// โ
ํ์ดํ ํจ์ ์ฝ๋ฐฑ์ this๋ฅผ ์ ์งํจ
processItems2: function () {
this.items.forEach((item) => {
console.log(this.name, item); // "Object" 1, "Object" 2, "Object" 3
});
},
// โ
forEach์ thisArg ๋งค๊ฐ๋ณ์ ์ฌ์ฉ
processItems3: function () {
this.items.forEach(function (item) {
console.log(this.name, item); // "Object" 1, "Object" 2, "Object" 3
}, this); // ๋ ๋ฒ์งธ ์ธ์๋ก this ์ง์
},
};
6. this binding rules summaryโ
this๋ฐ์ธ๋ฉ ๊ท์น ์์ฝ
์ฐ์ ์์(๋์ ์)โ
// 1. new ๋ฐ์ธ๋ฉ(์ต๊ณ ์ฐ์ ์์)
function Person(name) {
this.name = name;
}
const john = new Person('John');
console.log(john.name); // "John"
// 2. ๋ช
์์ ๋ฐ์ธ๋ฉ(call/apply/bind)
function greet() {
console.log(this.name);
}
const obj = { name: 'Object' };
greet.call(obj); // "Object"
// 3. ์์์ ๋ฐ์ธ๋ฉ(๊ฐ์ฒด ๋ฉ์๋)
const obj2 = {
name: 'Object2',
greet: greet,
};
obj2.greet(); // "Object2"
// 4. ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ(์ต์ ์ฐ์ ์์)
greet(); // undefined(์๊ฒฉ ๋ชจ๋) ๋๋ window.name
Function vs Arrow Function ๋น๊ตํโ
| ํน์ฑ | Function | Arrow Function |
|---|---|---|
์์ฒด this ๋ณด์ | โ ์์ | โ ์์ |
this ๊ฒฐ์ ์์ธ | ํธ์ถ ๋ฐฉ์ | ์ ์ ์์น(๋ ์์ปฌ ์ค์ฝํ) |
call/apply/bind๋ก this ๋ณ๊ฒฝ ๊ฐ๋ฅ | โ ๊ฐ๋ฅ | โ ๋ถ๊ฐ๋ฅ |
| ์์ฑ์๋ก ์ฌ์ฉ ๊ฐ๋ฅ | โ ๊ฐ๋ฅ | โ ๋ถ๊ฐ๋ฅ |
arguments ๊ฐ์ฒด ๋ณด์ | โ ์์ | โ ์์ |
| ์ ํฉํ ์ํฉ | ๊ฐ์ฒด ๋ฉ์๋, ์์ฑ์ | ์ฝ๋ฐฑ ํจ์, ์ธ๋ถ this ์์์ด ํ์ํ ๊ฒฝ์ฐ |
๊ธฐ์ต๋ฒโ
"ํ์ดํ๋ ์์, ํจ์๋ ํธ์ถ"
- ํ์ดํ ํจ์:
this๋ ์ธ๋ถ ์ค์ฝํ์์ ์์๋๋ฉฐ, ์ ์ ์์ ์ ๊ฒฐ์ ๋จ- ์ผ๋ฐ ํจ์:
this๋ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ฉฐ, ์คํ ์์ ์ ๊ฒฐ์ ๋จ
7. Best practicesโ
๋ชจ๋ฒ ์ฌ๋ก
โ ๊ถ์ฅ ๋ฐฉ๋ฒโ
// 1. ๊ฐ์ฒด ๋ฉ์๋์๋ ์ผ๋ฐ ํจ์ ๋๋ ES6 ๋ฉ์๋ ์ถ์ฝ ์ฌ์ฉ
const obj = {
name: 'Object',
// โ
์ข์: ์ผ๋ฐ ํจ์
greet: function () {
console.log(this.name);
},
// โ
์ข์: ES6 ์ถ์ฝ
introduce() {
console.log(this.name);
},
};
// 2. ์ฝ๋ฐฑ ํจ์์๋ ํ์ดํ ํจ์ ์ฌ์ฉ
class Component {
constructor() {
this.name = 'Component';
}
mount() {
// โ
์ข์: ํ์ดํ ํจ์๊ฐ this๋ฅผ ์ ์งํจ
setTimeout(() => {
console.log(this.name);
}, 1000);
}
}
// 3. ๋์ this๊ฐ ํ์ํ ๊ฒฝ์ฐ ์ผ๋ฐ ํจ์ ์ฌ์ฉ
const button = {
label: 'Click me',
// โ
์ข์: DOM ์์์ this์ ์ ๊ทผํด์ผ ํจ
handleClick: function () {
console.log(this); // button DOM ์์
},
};
โ ๋น๊ถ์ฅ ๋ฐฉ๋ฒโ
// 1. ๊ฐ์ฒด ๋ฉ์๋์ ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ์ง ์์
const obj = {
name: 'Object',
// โ ๋์จ: this๊ฐ obj๋ฅผ ๊ฐ๋ฆฌํค์ง ์์
greet: () => {
console.log(this.name); // undefined
},
};
// 2. ์์ฑ์์ ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ์ง ์์
// โ ๋์จ: ํ์ดํ ํจ์๋ ์์ฑ์๋ก ์ฌ์ฉํ ์ ์์
const Person = (name) => {
this.name = name; // ์ค๋ฅ!
};
// 3. arguments์ ์ ๊ทผํด์ผ ํ ๋ ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ์ง ์์
// โ ๋์จ: ํ์ดํ ํจ์์๋ arguments๊ฐ ์์
const sum = () => {
console.log(arguments); // ReferenceError
};