๐ 22์ฅ, this
๐ ๋ฐฐ์ด ๋ด์ฉ ๋ฐ ๊ธฐ์ตํ๊ณ ์ถ์ ๋ด์ฉ
this ํค์๋
this ํค์๋: ์์ ์ด ์ํ ๊ฐ์ฒด ๋๋ ์์ ์ด ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ์๊ธฐ ์ฐธ์กฐ ๋ณ์
- this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ์ํด ๋์ ์ผ๋ก ๊ฒฐ์ ๋จ
this ๋ฐ์ธ๋ฉ์ ์์ ์๋ ์ฝ๋
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// this๋ ์ด๋์๋ ์ง ์ฐธ์กฐ ๊ฐ๋ฅํ๋ค. // ์ ์ญ์์ this๋ ์ ์ญ ๊ฐ์ฒด window๋ฅผ ๊ฐ๋ฆฌํจ๋ค. console.log(this); // window function square(number) { // ์ผ๋ฐ ํจ์ ๋ด๋ถ์์ this๋ ์ ์ญ ๊ฐ์ฒด window๋ฅผ ๊ฐ๋ฆฌํจ๋ค. console.log(this); // window return number * number; } square(2); const person = { name: 'Lee', getName() { // ๋ฉ์๋ ๋ด๋ถ์์ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค. console.log(this); // {name: "Lee", getName: ฦ} return this.name; } }; console.log(person.getName()); // Lee function Person(name) { this.name = name; // ์์ฑ์ ํจ์ ๋ด๋ถ์์ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค. console.log(this); // Person {name: "Lee"} } const me = new Person('Lee');
ํจ์ ํธ์ถ ๋ฐฉ์๊ณผ this ๋ฐ์ธ๋ฉ
ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ์
์ผ๋ฐ ํจ์ ํธ์ถ
์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ ๋ชจ๋ ํจ์(์ค์ฒฉํจ์, ์ฝ๋ฐฑํจ์ ํฌํจ) ๋ด๋ถ์ this์๋ ์ ์ญ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// ๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉํจ์๋ ์ฝ๋ฐฑํจ์์ this ๋ฐ์ธ๋ฉ์ ๋ฉ์๋์ this ๋ฐ์ธ๋ฉ๊ณผ ์ผ์น์ํค๋ ๋ฐฉ๋ฒ1 var value = 1; const obj = { value: 100, foo() { // this ๋ฐ์ธ๋ฉ(obj)์ ๋ณ์ that์ ํ ๋นํ๋ค. const that = this; // ์ฝ๋ฐฑ ํจ์ ๋ด๋ถ์์ this ๋์ that์ ์ฐธ์กฐํ๋ค. setTimeout(function () { console.log(that.value); // 100 }, 100); } }; obj.foo();
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// this๋ฅผ ๋ช ์์ ์ผ๋ก ๋ฐ์ธ๋ฉ ํ๋ ๋ฐฉ๋ฒ var value = 1; const obj = { value: 100, foo() { // ์ฝ๋ฐฑ ํจ์์ ๋ช ์์ ์ผ๋ก this๋ฅผ ๋ฐ์ธ๋ฉํ๋ค. setTimeout(function () { console.log(this.value); // 100 }.bind(this), 100); } }; obj.foo();
1 2 3 4 5 6 7 8 9 10 11 12
// ํ์ดํ ํจ์๋ฅผ ์ด์ฉํ์ฌ this ๋ฐ์ธ๋ฉ ์ผ์น์ํค๋ ๋ฐฉ๋ฒ var value = 1; const obj = { value: 100, foo() { // ํ์ดํ ํจ์ ๋ด๋ถ์ this๋ ์์ ์ค์ฝํ์ this๋ฅผ ๊ฐ๋ฆฌํจ๋ค. setTimeout(() => console.log(this.value), 100); // 100 } }; obj.foo();
๋ฉ์๋ ํธ์ถ
๋ฉ์๋๋ฅผ ํธ์ถํ ๋ ๋ฉ์๋ ์ด๋ฆ ์์ ๋ง์นจํ(.) ์ฐ์ฐ์ ์์ ๊ธฐ์ ํ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋จ
๋ฉ์๋ ๋ด๋ถ์ this๋ ํ๋กํผํฐ๋ก ๋ฉ์๋๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฐ์ฒด์ ๊ด๊ณ๊ฐ ์์ผ๋ฉฐ, ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด์ ๋ฐ์ธ๋๋จ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// getName ๋ฉ์๋๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ํ๋กํผํฐ์ ํ ๋นํ์ฌ ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฉ์๋๊ฐ ๋ ์ ์๊ฑฐ๋ // ์ผ๋ฐ ๋ณ์์ ํ ๋นํ์ฌ ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ ์ ์์ const anotherPerson = { name: 'Kim' }; // getName ๋ฉ์๋๋ฅผ anotherPerson ๊ฐ์ฒด์ ๋ฉ์๋๋ก ํ ๋น anotherPerson.getName = person.getName; // getName ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด๋ anotherPerson์ด๋ค. console.log(anotherPerson.getName()); // Kim // getName ๋ฉ์๋๋ฅผ ๋ณ์์ ํ ๋น const getName = person.getName; // getName ๋ฉ์๋๋ฅผ ์ผ๋ฐ ํจ์๋ก ํธ์ถ console.log(getName()); // '' // ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ getName ํจ์ ๋ด๋ถ์ this.name์ ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name๊ณผ ๊ฐ๋ค. // ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์์ window.name์ ๋ธ๋ผ์ฐ์ ์ฐฝ์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋นํธ์ธ ํ๋กํผํฐ์ด๋ฉฐ ๊ธฐ๋ณธ๊ฐ์ ''์ด๋ค. // Node.js ํ๊ฒฝ์์ this.name์ undefined๋ค.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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
์์ฑ์ ํจ์ ํธ์ถ
์์ฑ์ ํจ์ ๋ด๋ถ์ this์๋ ์์ฑ์ ํจ์๊ฐ (๋ฏธ๋์) ์์ฑํ ์ธ์คํด์ค๊ฐ ๋ฐ์ธ๋ฉ
new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก ํธ์ถ๋์ง ์์ผ๋ฉด ์ผ๋ฐํจ์๋ก ๋์๋จ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// ์์ฑ์ ํจ์ function Circle(radius) { // ์์ฑ์ ํจ์ ๋ด๋ถ์ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค. this.radius = radius; this.getDiameter = function () { return 2 * this.radius; }; } // ๋ฐ์ง๋ฆ์ด 5์ธ Circle ๊ฐ์ฒด๋ฅผ ์์ฑ const circle1 = new Circle(5); // ๋ฐ์ง๋ฆ์ด 10์ธ Circle ๊ฐ์ฒด๋ฅผ ์์ฑ const circle2 = new Circle(10); console.log(circle1.getDiameter()); // 10 console.log(circle2.getDiameter()); // 20 // new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํ์ง ์์ผ๋ฉด ์์ฑ์ ํจ์๋ก ๋์ํ์ง ์๋๋ค. ์ฆ, ์ผ๋ฐ์ ์ธ ํจ์์ ํธ์ถ์ด๋ค. const circle3 = Circle(15); // ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ Circle์๋ ๋ฐํ๋ฌธ์ด ์์ผ๋ฏ๋ก ์๋ฌต์ ์ผ๋ก undefined๋ฅผ ๋ฐํํ๋ค. console.log(circle3); // undefined // ์ผ๋ฐ ํจ์๋ก ํธ์ถ๋ Circle ๋ด๋ถ์ this๋ ์ ์ญ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค. console.log(radius); // 15
Function.prototype.apply/call/bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ
apply, call, bind๋ Function.prototype์ ๋ฉ์๋์ด๋ฏ๋ก ๋ชจ๋ ํจ์๊ฐ ์์๋ฐ์ ์ฌ์ฉ ๊ฐ๋ฅํจ
apply์ call ๋ฉ์๋์ ๋ณธ์ง์ ์ธ ๊ธฐ๋ฅ์ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ. ํธ์ถํ๋ฉด์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ํน์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ ํจ์์ this์ ๋ฐ์ธ๋ฉํจ
apply์ call ๋ฉ์๋์ ๋ํ์ ์ธ ์ฉ๋๋ arguments ๊ฐ์ฒด์ ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด์ ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
function getThisBinding() { console.log(arguments); return this; } // this๋ก ์ฌ์ฉํ ๊ฐ์ฒด const thisArg = { a: 1 }; // getThisBinding ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ฒด๋ฅผ getThisBinding ํจ์์ this์ ๋ฐ์ธ๋ฉํ๋ค. // apply ๋ฉ์๋๋ ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก ๋ฌถ์ด ์ ๋ฌํ๋ค. console.log(getThisBinding.apply(thisArg, [1, 2, 3])); // Arguments(3) [1, 2, 3, callee: ฦ, Symbol(Symbol.iterator): ฦ] // {a: 1} // call ๋ฉ์๋๋ ํธ์ถํ ํจ์์ ์ธ์๋ฅผ ์ผํ๋ก ๊ตฌ๋ถํ ๋ฆฌ์คํธ ํ์์ผ๋ก ์ ๋ฌํ๋ค. console.log(getThisBinding.call(thisArg, 1, 2, 3)); // Arguments(3) [1, 2, 3, callee: ฦ, Symbol(Symbol.iterator): ฦ] // {a: 1}
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด์ ๋ฐฐ์ด๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ function convertArgsToArray() { console.log(arguments); // arguments ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํ // Array.prototype.slice๋ฅผ ์ธ์์์ด ํธ์ถํ๋ฉด ๋ฐฐ์ด์ ๋ณต์ฌ๋ณธ์ ์์ฑํ๋ค. const arr = Array.prototype.slice.call(arguments); // const arr = Array.prototype.slice.apply(arguments); console.log(arr); return arr; } convertArgsToArray(1, 2, 3); // [1, 2, 3]
bind ๋ฉ์๋๋ apply์ call ๋ฉ์๋์ ๋ฌ๋ฆฌ ํจ์๋ฅผ ํธ์ถํ์ง ์๊ณ this๋ก ์ฌ์ฉํ ๊ฐ์ฒด๋ง ์ ๋ฌํจ
bind ๋ฉ์๋๋ ๋ฉ์๋์ this์ ๋ฉ์๋ ๋ด๋ถ์ ์ค์ฒฉํจ์ ๋๋ ์ฝ๋ฐฑํจ์์ this๊ฐ ๋ถ์ผ์นํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ ์ฉํ๊ฒ ์ฌ์ฉ
1 2 3 4 5 6 7 8 9 10 11
const person = { name: 'Lee', foo(callback) { // bind ๋ฉ์๋๋ก callback ํจ์ ๋ด๋ถ์ this ๋ฐ์ธ๋ฉ์ ์ ๋ฌ setTimeout(callback.bind(this), 100); } }; person.foo(function () { console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee. });
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// this ๋ฐ์ธ๋ฉ์ ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๋ค. const foo = function () { console.dir(this); }; // ๋์ผํ ํจ์๋ ๋ค์ํ ๋ฐฉ์์ผ๋ก ํธ์ถํ ์ ์๋ค. // 1. ์ผ๋ฐ ํจ์ ํธ์ถ // foo ํจ์๋ฅผ ์ผ๋ฐ์ ์ธ ๋ฐฉ์์ผ๋ก ํธ์ถ // foo ํจ์ ๋ด๋ถ์ this๋ ์ ์ญ ๊ฐ์ฒด window๋ฅผ ๊ฐ๋ฆฌํจ๋ค. foo(); // window // 2. ๋ฉ์๋ ํธ์ถ // foo ํจ์๋ฅผ ํ๋กํผํฐ ๊ฐ์ผ๋ก ํ ๋นํ์ฌ ํธ์ถ // foo ํจ์ ๋ด๋ถ์ this๋ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด obj๋ฅผ ๊ฐ๋ฆฌํจ๋ค. const obj = { foo }; obj.foo(); // obj // 3. ์์ฑ์ ํจ์ ํธ์ถ // foo ํจ์๋ฅผ new ์ฐ์ฐ์์ ํจ๊ป ์์ฑ์ ํจ์๋ก ํธ์ถ // foo ํจ์ ๋ด๋ถ์ this๋ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํจ๋ค. new foo(); // foo {} // 4. Function.prototype.apply/call/bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ // foo ํจ์ ๋ด๋ถ์ this๋ ์ธ์์ ์ํด ๊ฒฐ์ ๋๋ค. const bar = { name: 'bar' }; foo.call(bar); // bar foo.apply(bar); // bar foo.bind(bar)(); // bar
ํจ์ ํธ์ถ ๋ฐฉ์ this ๋ฐ์ธ๋ฉ ์ผ๋ฐ ํจ์ ํธ์ถ ์ ์ญ ๊ฐ์ฒด ๋ฉ์๋ ํธ์ถ ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฐ์ฒด ์์ฑ์ ํจ์ ํธ์ถ ์์ฑ์ ํจ์๊ฐ ์์ฑํ ์ธ์คํด์ค Function.prototype.apply/call/bind ๋ฉ์๋์ ์ํ ๊ฐ์ ํธ์ถ Function.prototype.apply/call/bind ๋ฉ์๋์ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌํ ๊ฐ์ฒด
โ๏ธ ์ฝ์ ์๊ฐ
๋๋ this๋ ํค์๋๋ ์๊ธฐ ์์ ์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์ผ๋ก๋ง ์๊ณ ์์๋ค. ํ์ง๋ง ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ํจ์ ํธ์ถ ๋ฐฉ์์ ๋ฐ๋ผ ๋์ ์ผ๋ก ๊ฒฐ์ ๋๊ธฐ ๋๋ฌธ์ ๋ฌด์กฐ๊ฑด ๊ฐ์ ๊ฒ์ ๊ฐ๋ฆฌํค๋๊ฒ ์๋๋ ๊ฒ์ ์๋ก ์๊ฒ ๋์๋ค.
โ ๊ถ๊ธํ ๋ด์ฉ์ด๋ ์ ์ดํด๋์ง ์๋ ๋ด์ฉ
- ์์