"๋ฉ์๋ ํธ์ถ ๋ฐฉ์์ ์ด์ฉํ ๋์๋ ํ์ดํ ํจ์๋ฅผ ์ ์ฐ์ง ์์์ผํ ๊น?"
ํจ์๋ฅผ ์ด๋์ "ํธ์ถ"ํ์๋์ง์ ๋ฐ๋ผ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ
ํจ์๋ฅผ ์ด๋์ "์ ์ธ"ํ์๋์ง์ ๋ฐ๋ผ ์์ ์ค์ฝํ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ
๋ค์ ๊ธ์์ ์ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ์ "ํ๋กํ ํ์ ๊ธฐ๋ฐ์ ๊ฐ์ฒด์งํฅ", "๋ ์์ปฌ์ค์ฝํ", "this", "์ค์ฝํ"์ ๊ฐ์ ๊ฐ๋ ์ ๋ํด ํ ๋ ผ๋ฌธ์ ์ฐธ๊ณ ํ์ฌ ์ด์ผ๊ธฐ๋ฅผ ํ์ด ์ค๋ช ํด์ฃผ์ญ๋๋ค!
medium - ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ ํ๋กํ ํ์ ์ ์ ํํ์๊น
์ถ์ฒ: tistory - [Javascript] ๋์ ์ค์ฝํ? ์ ์ ์ค์ฝํ?
์์๋ c์ธ์ด์ด๋ค.
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo();
bar();
์ ์ ์ค์ฝํ์ผ๋
๋์ ์ค์ฝํ์ผ๋
this binding: ์๋ฐ์คํฌ๋ฆฝํธ์์ ํจ์๊ฐ ํธ์ถ๋๋ ๋ฐฉ์์ ๋ฐ๋ผ ๊ฒฐ์ ๋๋ this ์ฐธ์กฐ
์ถ์ฒ: tistory - [JS] ์์ญ๋ฌ์ญ ์๋ฐ์คํฌ๋ฆฝํธ this ๋ฐ์ธ๋ฉ
this ๋ฐ์ธ๋ฉ์ ๊ท์น
๋ค์ ๋ฐ์ธ๋ฉ ๊ท์น๋ค์ ํด๋น๋์ง ์๋ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ์ ํด๋นํ๋ฉฐ, ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ์ ๊ฒฝ์ฐ this๋ ์ ์ญ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค. (์ฝ๋ฐฑ ํจ์ ๋ฑ)
(๋ธ๋ผ์ฐ์ ์ผ ๊ฒฝ์ฐ window / noode.js ํ๊ฒฝ์ผ ๊ฒฝ์ฐ global)
function foo() {
const a = 10;
console.log(this); // window
console.log(this.a); // undefined
}
foo();
ํ์ง๋ง use strict
๋ชจ๋์์๋ ๊ธฐ๋ณธ ๋ฐ์ธ๋ฉ ๋์์์ ์ ์ญ ๊ฐ์ฒด๋ ์ ์ธ๋๋ค.
ํจ์๊ฐ ๊ฐ์ฒด์ ๋ฉ์๋๋ก์ ํธ์ถ๋๋ ์ํฉ์์ this๊ฐ ๋ฐ์ธ๋ฉ ๋ ๋๋ฅผ ์๋ฏธํ๋ค.
์์์ ๋ฐ์ธ๋ฉ์ ๊ฒฝ์ฐ this๋ ํด๋น ํจ์๋ฅผ ํธ์ถํ ๊ฐ์ฒด, ์ฆ ์ฝํ
์คํธ ๊ฐ์ฒด์ ๋ฐ์ธ๋ฉ๋๋ค.
const foo = {
a: 20,
bar: function () {
console.log(this); // foo object
console.log(this.a); // 20
}
}
foo.bar();
ํ์ง๋ง ํจ์์ ๋ ํผ๋ฐ์ค๋ฅผ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌํ๋ ์ํฉ์์๋ ์์์ ๋ฐ์ธ๋ฉ์ด ์ ์ฉ๋์ง ์๋๋ค. ์ด ๋ this๋ ์ ์ญ ๊ฐ์ฒด์ด๋ค.
setTimeout(foo.bar, 1); // ?
๋ช
์์ ๋ฐ์ธ๋ฉ์๋ call()
, apply()
, bind()
๋ฅผ ์ฌ์ฉํ๋ค.
์ด๋ ๋ชจ๋ Function์ ํ๋กํ ํ์
๋ฉ์๋์ด๋ค.
์ถ์ฒ: github - JS - this๋ฅผ ๋ณ๊ฒฝํ๋ call(), apply(), bind()
๊ตฌ๋ฌธ: func.call(thisArg[, arg1[, arg2[, โฆ]]])
์์1) ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฉ์๋ ์ฌ์ฉํ๊ธฐ
let obj1 = {
name: 'kim',
sayHello () {
console.log(`hello ${this.name}!`);
}
}
let obj2 = {
name: 'park',
}
obj1.sayHello.call(obj2); // hello park!
์์2) ๋ค๋ฅธ ์์ฑ์ ํจ์ ๋ฉค๋ฒ ๊ฐ์ ธ์ค๊ธฐ
const getSetMethod = function() {
this.getName = function() {
return this.name;
}
this.setName = function(name) {
this.name = name;
}
}
class Person {
constructor(name) {
this.name = name;
getSetMethod.call(this);
}
}
const kim = new Person('kim');
kim.getName(); // kim
kim.setName('lee'); // lee
์์3) ๋ด๋ถํจ์์ this๊ฐ ์์ ์ค์ฝํ๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ๋ณ๊ฒฝํ๊ธฐ
class Person {
constructor(name) {
this.name = name;
}
greeting() {
function sayHello () {
console.log(`hello ${this.name}!`);
}
// sayHello(); // undefined ์๋ฌ
sayHello.call(this);
}
}
const kim = new Person('kim');
kim.greeting();
์์4) this์ ํจ๊ป ๋งค๊ฐ๋ณ์ ๋๊ธฐ๊ธฐ
const greeting = {
sayHello(greetingWord) {
return `${greetingWord} ${this.name}!`
}
}
const person = {
name: 'kim'
}
greeting.sayHello.call(person, "์๋
ํ์ธ์~!");
// ์๋
ํ์ธ์~! kim!
๊ตฌ๋ฌธ: func.apply(thisArg, [argsArray])
apply()๋ call()๊ณผ ๊ธฐ๋ฅ์ด ๋์ผํ์ง๋ง, ์ธ์๋ฅผ ์ ๋ฌํ๋ ๋ฐฉ์์์๋ง ์ฐจ์ด๊ฐ ์๋ค.
sayHello(greetingWord) {
return `${greetingWord} ${this.name}!`
}
}
const person = {
name: 'kim'
}
greeting.sayHello.apply(person, ["์๋
ํ์ธ์~!"]);
call()๊ณผ apply()์ ๊ฐ์ ์ญํ (this ๋ฐ์ธ๋ฉ ๊ฐ์ฒด ๋ณ๊ฒฝ)์ ํ์ง๋ง ํจ์๋ฅผ ์คํํ๋ ๊ฒ์ด ์๋ ์๋ก์ด ํจ์๋ฅผ ๋ฐํํ๋ค.
let obj1 = {
name: 'kim',
sayHello () {
console.log(`hello ${this.name}!`);
}
}
let obj2 = {
name: 'park',
}
obj1.sayHello.call(obj2); // hello park!
const fn = obj1.sayHello.bind(obj2);
fn(); // hello park!
์์ฑ์ ํจ์์์๋ this ํค์๋๋ฅผ ํด๋น ์์ฑ์๋ฅผ ์ด์ฉํด ์์ฑํ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๋ก ์ฌ์ฉํ๋ค.
function Foo() {
this.a = 20;
}
const foo = new Foo();
console.log(foo.a); // 20
ES6์ ์ถ๊ฐ๋ ํ์ดํ ํจ์(Arrow Function)๋ this๋ฅผ ๋ฐ์ธ๋ฉํ ๋ ์์ ์ค๋ช ํ ๊ท์น๋ค์ด ์ ์ฉ๋์ง ์๊ณ , this์ ์ดํ์ ์ค์ฝํ(Lexical scope)๊ฐ ์ ์ฉ๋๋ค. ์ฆ, ํ์ดํ ํจ์๋ฅผ ์ ์ํ๋ ์์ ์ ์ปจํ ์คํธ ๊ฐ์ฒด๊ฐ this์ ๋ฐ์ธ๋ฉ๋๋ค.
const foo = {
a: 20,
bar: function () {
setTimeout(() => {
console.log(this.a);
}, 1);
}
}
foo.bar(); // 20
var value = 1;
var obj = {
value : 100,
func1 : function(){
this.value += 1;
console.log("func1()'s value: " + this.value); //func1()'s value: 101
func2 = function(){
this.value += 1;
console.log("func2()'s value: " + this.value); //func2()'s value: 2
}
func2();
}
};
obj.func1();
func2๋ obj์ ๋ฐ์ธ๋ฉ๋๋๋ก ํ๊ณ ์ถ๋ค๋ฉด?
1. func2๋ฅผ ํ์ดํ ํจ์๋ก ๋ณ๊ฒฝํ๋ค.
var value = 1;
var obj = {
value : 100,
func1 : function(){
this.value += 1;
console.log("func1()'s value: " + this.value); //func1()'s value: 101
func2 = () => {
this.value += 1;
console.log("func2()'s value: " + this.value); //func2()'s value: 102
}
func2();
}
};
obj.func1();
var value = 1;
var obj = {
value : 100,
func1 : function(){
const _this = this;
this.value += 1;
console.log("func1()'s value: " + this.value); //func1()'s value: 101
func2 = () => {
this.value += 1;
console.log("func2()'s value: " + _this.value); //func2()'s value: 102
}
func2();
}
};
obj.func1();
์ถ์ฒ: mdn - ํ์ดํ ํจ์
ํ์ดํ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ์ ํ์ ์ด ์๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๊ฐ ์๋ค๊ณ ํ๋ค๋ฉด,
๋ฉ์๋๋ ๊ฐ์ฒด์ ์ข
์๋์ด ๊ฐ์ฒด์ ๊ฐ์ ์ฐธ์กฐํด์ผ ํ๋ค๊ณ ์๊ฐํ์ง๋ง,
ํ์ดํ ํจ์๋ this ๋ฐ์ธ๋ฉ์ด ์๊ณ ๋ ์ค์ปฌ ์ค์ฝํ๊ฐ ์ ์ฉ๋๋ค๋ ์ ์์ ๋ฉ์๋๋ก ์ฌ์ฉํ๊ธฐ์ ์ ์ ํ์ง ์๋ค๋ ์๋ฏธ์ด๋ค.
'use strict';
var obj = { // does not create a new scope
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log( this.i, this)
}
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}