๋ฉ์๋๋ ์์ ์ด ์ํ ๊ฐ์ฒด์ ์ํ, ์ฆ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๊ณ ๋ณ๊ฒฝํ ์ ์์ด์ผ ํ๋ค.
์ด๋ ๋ฉ์๋๊ฐ ์์ ์ด ์ํ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๋ ค๋ฉด ๋จผ์ ์์ ์ด ์ํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๋ฅผ ์ฐธ์กฐํ ์ ์์ด์ผ ํ๋ค.
1. this?
- ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ ์ฐธ์กฐ ๋ณ์(self-referencing variable)
- this๋ฅผ ํตํด ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
- ๋จ, this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ, ์ฆ this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
- ํด๋์ค ๊ธฐ๋ฐ ์ธ์ด์์ this๋ ์ธ์ ๋ ํด๋์ค๊ฐ ์์ฑํ๋ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋๋ฐ
, ์๋ฐ์คํฌ๋ฆฝํธ์ this๋ ํจ์๊ฐ ํธ์ถ๋๋ ๋ฐฉ์์ ๋ฐ๋ผ this์ ๋ฐ์ธ๋ฉ๋ ๊ฐ, ์ฆ this ๋ฐ์ธ๋ฉ์ด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
- this๋ ์ฝ๋ ์ด๋์์๋ ์ฐธ์กฐ ๊ฐ๋ฅํ๋ค. ์ ์ญ์์๋ ํจ์ ๋ด๋ถ์์๋ ์ฐธ์กฐ ๊ฐ๋ฅ
1-1. ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฉ์๋ ๋ด๋ถ์ this
- ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
const circle = {
radius: 5,
getDiameter() {
// this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
return 1 * this.radius;
}
}
1-2. ์์ฑ์ ํจ์ ๋ด๋ถ์ this
- ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
function Circle(radius) {
// this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
this.radius = radius;
}
Circle.prototype.getDiameter = function() {
// this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค ๊ฐ๋ฆฌํจ๋ค.
return 1 * this.radius
}
// ์ธ์คํด์ค ์์ฑ
const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
2. ํจ์ ํธ์ถ ๋ฐฉ์๊ณผ this ๋ฐ์ธ๋ฉ
- this์ ๋ฐ์ธ๋ฉ ๋ ๊ฐ์ ํจ์ ํธ์ถ ๋ฐฉ์, ์ฆ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋์๋์ง์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
2-1. this ๋ฐ์ธ๋ฉ
- ๋ฐ์ธ๋ฉ : ์๋ณ์์ ๊ฐ์ ์ฐ๊ฒฐํ๋ ๊ณผ์
- this ๋ฐ์ธ๋ฉ : this์ this๊ฐ ๊ฐ๋ฆฌํฌ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉ ํ๋ ๊ฒ์ด๋ค.
๋ ์์ปฌ ์ค์ฝํ์ this ๋ฐ์ธ๋ฉ์ ๊ฒฐ์ ์๊ธฐ๊ฐ ๋ค๋ฅด๋ค.
- ๋ ์์ปฌ ์ค์ฝํ(ํจ์์ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ์) : ํจ์ ์ ์๊ฐ ํ๊ฐ๋์ด ํจ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ์์ ์ ์์ ์ค์ฝํ ๊ฒฐ์
- this ๋ฐ์ธ๋ฉ : ํจ์ ํธ์ถ ์์ ์ ๊ฒฐ์
ํจ์ ํธ์ถ ๋ฐฉ์ |
this ๋ฐ์ธ๋ฉ |
์ผ๋ฐ ํจ์ ํธ์ถ |
์ ์ญ ๊ฐ์ฒด |
๋ฉ์๋ ํธ์ถ |
๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด |
์์ฑ์ ํจ์ ํธ์ถ |
์์ฑ์ ํจ์๊ฐ (๋ฏธ๋์) ์์ฑํ ์ธ์คํด์ค |
Function.prototype.apply / call / bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ | Function.prototype.apply / call / bind ๋ฉ์๋์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ฒด |
2-2. ์ผ๋ฐ ํจ์ ํธ์ถ
- ๊ธฐ๋ณธ์ ์ผ๋ก Global Object(์ ์ญ ๊ฐ์ฒด) ๋ฐ์ธ๋ฉ ๋๋ค.
function foo() {
console.log("foo => ", this); // window
function bar() {
console.log("bar => ", this); // window
}
bar();
}
foo();
- ๋ค๋ง this๋ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ๊ฐ์ฒด์ ํ๋กํผ์น๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํ ์๊ธฐ ์ฐธ์กฐ ๋ณ์์ด๋ฏ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์๋ ์ผ๋ฐ ํจ์์๋ this๊ฐ ์๋ฏธ ์์.
- strict mode๊ฐ ์ ์ฉ๋ ์ผ๋ฐ ํจ์ ๋ด๋ถ์ this๋ undefined ๋ฐ์ธ๋ฉ ๋๋ค.
function foo() {
'use stricr';
console.log("foo => ", this); // undefined
function bar() {
console.log("bar => ", this); // undefined
}
bar();
}
foo();
- ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉ ํจ์๋ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ฉด ์ค์ฒฉ ํจ์ ๋ด๋ถ์ this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
console.log("foo => ", this); // {value: 100, foo: f}
console.log("foo value => ", this.value); // 100
// ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉ ํจ์
function bar() {
console.log("bar => ", this); // window
console.log("bar value => ", this.value); // 1
}
// ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉํจ์๋ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ฉด
// ์ค์ฒฉ ํจ์ ๋ด๋ถ์ This๋ ์ ์ญ๊ฐ์ฒด ๋ฐ์ธ๋ฉ ๋๋ค
bar();
}
};
obj.foo();
- ์ฝ๋ฐฑํจ์๊ฐ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ค๋ฉด ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
console.log('foo => ', this); // {value: 100, foo: f}
// ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this ์ ์ญ ๊ฐ์ฒด ๋ฐ์ธ๋ฉ ๋๋ค.
setTimeout(function () {
console.log('์ฝ๋ฐฑํจ์ => ', this); // window
console.log('์ฝ๋ฐฑํจ์๊ฐ => ', this.value); // 1
}, 100)
}
};
obj.foo();
2-3. ํ์ดํ ํจ์ ์ฌ์ฉํ this ๋ฐ์ธ๋ฉ
- ํ์ดํ ํจ์ ๋ด๋ถ์ this๋ ์์ ์ค์ฝํ์ this๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(() => {
console.log(this.value)
}, 100) // 100
}
};
obj.foo();
2-4. ๋ฉ์๋ ํธ์ถ
- ๋ฉ์๋ ๋ด๋ถ์ this์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด, ์ฆ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๋ฉ์๋ ์ด๋ฆ ์์ ๋ง์นจํ(.) ์ฐ์ฐ์ ์์ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
- ์ฃผ์!! ์์ ํ ๊ฐ์ฒด๊ฐ ์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
const person = {
name: 'Lee',
getName() {
// ๋ฉ์๋ ๋ด๋ถ์ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
return this.name;
}
};
// ๋ฉ์๋ getName ํธ์ถํ ๊ฐ์ฒด๋ person!
// getName ํ๋กํผํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ํจ์ ๊ฐ์ฒด๋ person ๊ฐ์ฒด์ ํฌํจ๋ ๊ฒ์ด ์๋
// , ๋
๋ฆฝ์ ์ผ๋ก ์กด์ฌํ๋ ๋ณ๋์ ๊ฐ์ฒด
// getName ๋ฉ์๋๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ํ๋กํผํฐ์ ํ ๋นํ๋ ๊ฒ์ผ๋ก ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฉ์๋๊ฐ ๋ ์๋ ์๊ณ
// ์ผ๋ฐ ๋ณ์์ ํ ๋นํ์ฌ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ ์๋ ์๋ค.
console.log(person.getName()); // Lee
2-5. ํ๋กํ ํ์ ๋ฉ์๋ ๋ด๋ถ์์ ์ฌ์ฉ๋ this
- ์ผ๋ฐ ๋ฉ์๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
const me = new Person('Lee');
// getName ํธ์ถํ ๋ฉ์๋ ==> me
console.log(me.getName()); // Lee
Person.prototype.name = 'kim';
// getName ํธ์ถํ ๋ฉ์๋ ==> Person.prototype
console.log(Person.prototype.getName()); // Kim
2-6. ์์ฑ์ ํจ์ ํธ์ถ
- ์์ฑ์ ํจ์ ๋ด๋ถ์ this์๋ ์์ฑ์ ํจ์๊ฐ (๋ฏธ๋์) ์์ฑํ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
- ์์ฑ์ ํจ์๋ ์ด๋ฆ ๊ทธ๋๋ก ๊ฐ์ฒด(์ธ์คํด์ค) ์์ฑํ๋ ํจ์
- ์ผ๋ฐํจ์์ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ์์ฑ์ ํจ์๋ฅผ ์ ์ํ๊ณ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ๋ฉด ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์
- new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ง ์์ผ๋ฉด ์ผ๋ฐ ํจ์๋ก ๋์
function Circle(radius) {
this.radius = raidus;
this.getDiameter = function () {
return 2 * this.radius;
}
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
console.log(circle1); // 10
console.log(circle2); // 20
// new ์์, ์ผ๋ฐํจ์ ํธ์ถ
const circle3 = Circle(15);
// undefined ๋ฐํ
console.log(circle3); // undefined
// ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ Circle ๋ด๋ถ์ this๋ ์ ์ญ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(radius); // 15
2-7. Function.prototype.apply / call / bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ
- apply์ call ๋ฉ์๋์ ๋ณธ์ง์ ์ธ ๊ธฐ๋ฅ์ ํจ์๋ฅผ ํธ์ถํ๋๊ฒ
- ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ํน์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ ํจ์์ this์ ๋ฐ์ธ๋ฉ ํ๋ค.
- ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด์ ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
apply |
call | bind |
ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก ๋ฌถ์ด ์ ๋ฌ |
ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ์ผํ๋ก ๊ตฌ๋ถํ ๋ฆฌ์คํธ ํ์์ผ๋ก ์ ๋ฌ |
apply, call ๊ณผ ๋ฌ๋ฆฌ ํจ์๋ฅผ ํธ์ถํ์ง ์๋๋ค. |
// apply, call
function getThisBinding() {
console.log(arguments);
return this;
}
const thisArg = { a: 1 };
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator): f]
// { a: 1 }
console.log(getThisBinding.call(thisArg, [1, 2, 3]));
// Arguments(3) [Array(3), callee: f, Symbol(Symbol.iterator): f]
// { a: 1 }
// bind
function getThisBinding() {
return this;
}
const thisArg = { a: 1 };
// bind ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ thisArg๋ก this ๋ฐ์ธ๋ฉ์ด ๊ต์ฒด๋
// getThisBinding ํจ์๋ฅผ ์๋กญ๊ฒ ์์ฑํด ๋ฐํํ๋ค.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind ๋ฉ์๋๋ ํจ์๋ฅผ ํธ์ถํ์ง๋ ์์ผ๋ฏ๋ก ๋ช
์์ ์ผ๋ก ํธ์ถํด์ผํ๋ค.
console.log(getThisBinding.bind(thisArg)()); // { a: 1 }
- bind ๋ฉ์๋๋ ๋ฉ์๋์ this์ ๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉ ํจ์ ๋๋ ์ฝ๋ฐฑ ํจ์์ this๊ฐ ๋ถ์ผ์นํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
const person = {
name: 'Lee',
foo(callback) {
// ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this๋ฅผ ์ธ๋ถ ํจ์ ๋ด๋ถ์ this์ ์ผ์น์์ผ์ผ ํ๋ค.
setTimeout(callback.bind(this), 100);
}
};
person.foo(function() {
console.log(`Hello my name is ${this.name}`);
})
๋ฉ์๋๋ ์์ ์ด ์ํ ๊ฐ์ฒด์ ์ํ, ์ฆ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๊ณ ๋ณ๊ฒฝํ ์ ์์ด์ผ ํ๋ค.
์ด๋ ๋ฉ์๋๊ฐ ์์ ์ด ์ํ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๋ ค๋ฉด ๋จผ์ ์์ ์ด ์ํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ์๋ณ์๋ฅผ ์ฐธ์กฐํ ์ ์์ด์ผ ํ๋ค.
1. this?
- ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ ์ฐธ์กฐ ๋ณ์(self-referencing variable)
- this๋ฅผ ํตํด ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
- ๋จ, this๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฐ, ์ฆ this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
- ํด๋์ค ๊ธฐ๋ฐ ์ธ์ด์์ this๋ ์ธ์ ๋ ํด๋์ค๊ฐ ์์ฑํ๋ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋๋ฐ
, ์๋ฐ์คํฌ๋ฆฝํธ์ this๋ ํจ์๊ฐ ํธ์ถ๋๋ ๋ฐฉ์์ ๋ฐ๋ผ this์ ๋ฐ์ธ๋ฉ๋ ๊ฐ, ์ฆ this ๋ฐ์ธ๋ฉ์ด ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
- this๋ ์ฝ๋ ์ด๋์์๋ ์ฐธ์กฐ ๊ฐ๋ฅํ๋ค. ์ ์ญ์์๋ ํจ์ ๋ด๋ถ์์๋ ์ฐธ์กฐ ๊ฐ๋ฅ
1-1. ๊ฐ์ฒด ๋ฆฌํฐ๋ด ๋ฉ์๋ ๋ด๋ถ์ this
- ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
const circle = {
radius: 5,
getDiameter() {
// this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
return 1 * this.radius;
}
}
1-2. ์์ฑ์ ํจ์ ๋ด๋ถ์ this
- ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
function Circle(radius) {
// this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
this.radius = radius;
}
Circle.prototype.getDiameter = function() {
// this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค ๊ฐ๋ฆฌํจ๋ค.
return 1 * this.radius
}
// ์ธ์คํด์ค ์์ฑ
const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
2. ํจ์ ํธ์ถ ๋ฐฉ์๊ณผ this ๋ฐ์ธ๋ฉ
- this์ ๋ฐ์ธ๋ฉ ๋ ๊ฐ์ ํจ์ ํธ์ถ ๋ฐฉ์, ์ฆ ํจ์๊ฐ ์ด๋ป๊ฒ ํธ์ถ๋์๋์ง์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค.
2-1. this ๋ฐ์ธ๋ฉ
- ๋ฐ์ธ๋ฉ : ์๋ณ์์ ๊ฐ์ ์ฐ๊ฒฐํ๋ ๊ณผ์
- this ๋ฐ์ธ๋ฉ : this์ this๊ฐ ๊ฐ๋ฆฌํฌ ๊ฐ์ฒด๋ฅผ ๋ฐ์ธ๋ฉ ํ๋ ๊ฒ์ด๋ค.
๋ ์์ปฌ ์ค์ฝํ์ this ๋ฐ์ธ๋ฉ์ ๊ฒฐ์ ์๊ธฐ๊ฐ ๋ค๋ฅด๋ค.
- ๋ ์์ปฌ ์ค์ฝํ(ํจ์์ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๋ฐฉ์) : ํจ์ ์ ์๊ฐ ํ๊ฐ๋์ด ํจ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ์์ ์ ์์ ์ค์ฝํ ๊ฒฐ์
- this ๋ฐ์ธ๋ฉ : ํจ์ ํธ์ถ ์์ ์ ๊ฒฐ์
ํจ์ ํธ์ถ ๋ฐฉ์ |
this ๋ฐ์ธ๋ฉ |
์ผ๋ฐ ํจ์ ํธ์ถ |
์ ์ญ ๊ฐ์ฒด |
๋ฉ์๋ ํธ์ถ |
๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด |
์์ฑ์ ํจ์ ํธ์ถ |
์์ฑ์ ํจ์๊ฐ (๋ฏธ๋์) ์์ฑํ ์ธ์คํด์ค |
Function.prototype.apply / call / bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ | Function.prototype.apply / call / bind ๋ฉ์๋์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ฒด |
2-2. ์ผ๋ฐ ํจ์ ํธ์ถ
- ๊ธฐ๋ณธ์ ์ผ๋ก Global Object(์ ์ญ ๊ฐ์ฒด) ๋ฐ์ธ๋ฉ ๋๋ค.
function foo() {
console.log("foo => ", this); // window
function bar() {
console.log("bar => ", this); // window
}
bar();
}
foo();
- ๋ค๋ง this๋ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ๊ฐ์ฒด์ ํ๋กํผ์น๋ ๋ฉ์๋๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํ ์๊ธฐ ์ฐธ์กฐ ๋ณ์์ด๋ฏ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ์ง ์๋ ์ผ๋ฐ ํจ์์๋ this๊ฐ ์๋ฏธ ์์.
- strict mode๊ฐ ์ ์ฉ๋ ์ผ๋ฐ ํจ์ ๋ด๋ถ์ this๋ undefined ๋ฐ์ธ๋ฉ ๋๋ค.
function foo() {
'use stricr';
console.log("foo => ", this); // undefined
function bar() {
console.log("bar => ", this); // undefined
}
bar();
}
foo();
- ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉ ํจ์๋ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ฉด ์ค์ฒฉ ํจ์ ๋ด๋ถ์ this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
console.log("foo => ", this); // {value: 100, foo: f}
console.log("foo value => ", this.value); // 100
// ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉ ํจ์
function bar() {
console.log("bar => ", this); // window
console.log("bar value => ", this.value); // 1
}
// ๋ฉ์๋ ๋ด์์ ์ ์ํ ์ค์ฒฉํจ์๋ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ฉด
// ์ค์ฒฉ ํจ์ ๋ด๋ถ์ This๋ ์ ์ญ๊ฐ์ฒด ๋ฐ์ธ๋ฉ ๋๋ค
bar();
}
};
obj.foo();
- ์ฝ๋ฐฑํจ์๊ฐ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋๋ค๋ฉด ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this์๋ ์ ์ญ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
console.log('foo => ', this); // {value: 100, foo: f}
// ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this ์ ์ญ ๊ฐ์ฒด ๋ฐ์ธ๋ฉ ๋๋ค.
setTimeout(function () {
console.log('์ฝ๋ฐฑํจ์ => ', this); // window
console.log('์ฝ๋ฐฑํจ์๊ฐ => ', this.value); // 1
}, 100)
}
};
obj.foo();
2-3. ํ์ดํ ํจ์ ์ฌ์ฉํ this ๋ฐ์ธ๋ฉ
- ํ์ดํ ํจ์ ๋ด๋ถ์ this๋ ์์ ์ค์ฝํ์ this๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(() => {
console.log(this.value)
}, 100) // 100
}
};
obj.foo();
2-4. ๋ฉ์๋ ํธ์ถ
- ๋ฉ์๋ ๋ด๋ถ์ this์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด, ์ฆ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๋ฉ์๋ ์ด๋ฆ ์์ ๋ง์นจํ(.) ์ฐ์ฐ์ ์์ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
- ์ฃผ์!! ์์ ํ ๊ฐ์ฒด๊ฐ ์๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
const person = {
name: 'Lee',
getName() {
// ๋ฉ์๋ ๋ด๋ถ์ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
return this.name;
}
};
// ๋ฉ์๋ getName ํธ์ถํ ๊ฐ์ฒด๋ person!
// getName ํ๋กํผํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ํจ์ ๊ฐ์ฒด๋ person ๊ฐ์ฒด์ ํฌํจ๋ ๊ฒ์ด ์๋
// , ๋
๋ฆฝ์ ์ผ๋ก ์กด์ฌํ๋ ๋ณ๋์ ๊ฐ์ฒด
// getName ๋ฉ์๋๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ํ๋กํผํฐ์ ํ ๋นํ๋ ๊ฒ์ผ๋ก ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฉ์๋๊ฐ ๋ ์๋ ์๊ณ
// ์ผ๋ฐ ๋ณ์์ ํ ๋นํ์ฌ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ ์๋ ์๋ค.
console.log(person.getName()); // Lee
2-5. ํ๋กํ ํ์ ๋ฉ์๋ ๋ด๋ถ์์ ์ฌ์ฉ๋ this
- ์ผ๋ฐ ๋ฉ์๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ ๋๋ค.
function Person(name) {
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
const me = new Person('Lee');
// getName ํธ์ถํ ๋ฉ์๋ ==> me
console.log(me.getName()); // Lee
Person.prototype.name = 'kim';
// getName ํธ์ถํ ๋ฉ์๋ ==> Person.prototype
console.log(Person.prototype.getName()); // Kim
2-6. ์์ฑ์ ํจ์ ํธ์ถ
- ์์ฑ์ ํจ์ ๋ด๋ถ์ this์๋ ์์ฑ์ ํจ์๊ฐ (๋ฏธ๋์) ์์ฑํ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ ๋๋ค.
- ์์ฑ์ ํจ์๋ ์ด๋ฆ ๊ทธ๋๋ก ๊ฐ์ฒด(์ธ์คํด์ค) ์์ฑํ๋ ํจ์
- ์ผ๋ฐํจ์์ ๋์ผํ ๋ฐฉ๋ฒ์ผ๋ก ์์ฑ์ ํจ์๋ฅผ ์ ์ํ๊ณ new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ๋ฉด ํด๋น ํจ์๋ ์์ฑ์ ํจ์๋ก ๋์
- new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ง ์์ผ๋ฉด ์ผ๋ฐ ํจ์๋ก ๋์
function Circle(radius) {
this.radius = raidus;
this.getDiameter = function () {
return 2 * this.radius;
}
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
console.log(circle1); // 10
console.log(circle2); // 20
// new ์์, ์ผ๋ฐํจ์ ํธ์ถ
const circle3 = Circle(15);
// undefined ๋ฐํ
console.log(circle3); // undefined
// ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ Circle ๋ด๋ถ์ this๋ ์ ์ญ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
console.log(radius); // 15
2-7. Function.prototype.apply / call / bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ
- apply์ call ๋ฉ์๋์ ๋ณธ์ง์ ์ธ ๊ธฐ๋ฅ์ ํจ์๋ฅผ ํธ์ถํ๋๊ฒ
- ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ํน์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ ํจ์์ this์ ๋ฐ์ธ๋ฉ ํ๋ค.
- ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด์ ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
apply |
call | bind |
ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก ๋ฌถ์ด ์ ๋ฌ |
ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ์ผํ๋ก ๊ตฌ๋ถํ ๋ฆฌ์คํธ ํ์์ผ๋ก ์ ๋ฌ |
apply, call ๊ณผ ๋ฌ๋ฆฌ ํจ์๋ฅผ ํธ์ถํ์ง ์๋๋ค. |
// apply, call
function getThisBinding() {
console.log(arguments);
return this;
}
const thisArg = { a: 1 };
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator): f]
// { a: 1 }
console.log(getThisBinding.call(thisArg, [1, 2, 3]));
// Arguments(3) [Array(3), callee: f, Symbol(Symbol.iterator): f]
// { a: 1 }
// bind
function getThisBinding() {
return this;
}
const thisArg = { a: 1 };
// bind ๋ฉ์๋๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ thisArg๋ก this ๋ฐ์ธ๋ฉ์ด ๊ต์ฒด๋
// getThisBinding ํจ์๋ฅผ ์๋กญ๊ฒ ์์ฑํด ๋ฐํํ๋ค.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind ๋ฉ์๋๋ ํจ์๋ฅผ ํธ์ถํ์ง๋ ์์ผ๋ฏ๋ก ๋ช
์์ ์ผ๋ก ํธ์ถํด์ผํ๋ค.
console.log(getThisBinding.bind(thisArg)()); // { a: 1 }
- bind ๋ฉ์๋๋ ๋ฉ์๋์ this์ ๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉ ํจ์ ๋๋ ์ฝ๋ฐฑ ํจ์์ this๊ฐ ๋ถ์ผ์นํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
const person = {
name: 'Lee',
foo(callback) {
// ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์ this๋ฅผ ์ธ๋ถ ํจ์ ๋ด๋ถ์ this์ ์ผ์น์์ผ์ผ ํ๋ค.
setTimeout(callback.bind(this), 100);
}
};
person.foo(function() {
console.log(`Hello my name is ${this.name}`);
})