setTimeoutì ë©ìë를 ì ë¬í ëì²ë¼, ê°ì²´ ë©ìë를 ì½ë°±ì¼ë¡ ì ë¬í ë âthis ì ë³´ê° ì¬ë¼ì§ëâ 문ì ê° ìê¹ëë¤.
ì´ë² ì±í°ìì ì´ ë¬¸ì 를 ì´ë»ê² í´ê²°í ì§ì ëí´ ììë³´ê² ìµëë¤.
ì¬ë¼ì§ âthisâ
ìì ë¤ìí ìì 를 íµí´ this ì ë³´ê° ì¬ë¼ì§ë 문ì 를 ê²½íí´ë³´ììµëë¤. ê°ì²´ ë©ìëê° ê°ì²´ ë´ë¶ê° ìë ë¤ë¥¸ ê³³ì ì ë¬ëì´ í¸ì¶ëë©´ thisê° ì¬ë¼ì§ëë¤.
setTimeoutì ì¬ì©í ìë ìììì thisê° ì´ë»ê² ì¬ë¼ì§ëì§ ì´í´ë´
ìë¤.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
setTimeout(user.sayHi, 1000); // Hello, undefined!
this.firstNameì´ "John"ì´ ëì´ì¼ íëë°, ì¼ë¿ì°½ì undefinedê° ì¶ë ¥ë©ëë¤.
ì´ë ê² ë ì´ì ë setTimeoutì ê°ì²´ìì ë¶ë¦¬ë í¨ìì¸ user.sayHiê° ì ë¬ë기 ë문ì
ëë¤. ì ììì ë§ì§ë§ ì¤ì ë¤ì ì½ëì ê°ìµëë¤.
let f = user.sayHi;
setTimeout(f, 1000); // user 컨í
ì¤í¸ë¥¼ ìì´ë²ë¦¼
ë¸ë¼ì°ì íê²½ìì setTimeout ë©ìëë ì¡°ê¸ í¹ë³í ë°©ìì¼ë¡ ëìí©ëë¤. ì¸ìë¡ ì ë¬ë°ì í¨ì를 í¸ì¶í ë, thisì window를 í ë¹í©ëë¤(Node.js íê²½ìì thisê° íì´ë¨¸ ê°ì²´ê° ëëë°, ì¬ê¸°ì ì¤ìíì§ ìì¼ë¯ë¡ ëì´ê°ê² ìµëë¤). ë°ë¼ì ì ììì this.firstNameì window.firstNameê° ëëë°, window ê°ì²´ì firstNameì´ ìì¼ë¯ë¡ undefinedê° ì¶ë ¥ë©ëë¤. ë¤ë¥¸ ì ì¬í ì¬ë¡ììë ëë¶ë¶ thisë undefinedê° ë©ëë¤.
ê°ì²´ ë©ìë를 ì¤ì ë©ìëê° í¸ì¶ëë ê³³(ìììì setTimeout ì¤ì¼ì¤ë¬)ì¼ë¡ ì ë¬íë ê²ì ì주 íí©ëë¤. ì´ë ê² ë©ìë를 ì ë¬í ë, 컨í
ì¤í¸ë ì ëë¡ ì ì§íë ¤ë©´ ì´ë»ê² í´ì¼ í ê¹ì?
ë°©ë² 1: ëí¼
ê°ì¥ ê°ë¨í í´ê²°ì± ì ëí¼ í¨ì를 ì¬ì©íë ê²ì ëë¤.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
setTimeout(function() {
user.sayHi(); // Hello, John!
}, 1000);
ì ììê° ìëí ëë¡ ëìíë ì´ì ë ì¸ë¶ ë ì컬 íê²½ìì user를 ë°ìì ë³´íµ ëì²ë¼ ë©ìë를 í¸ì¶í기 ë문ì
ëë¤.
ê°ì¡° íìí ì¤ì ìëì ê°ì´ ë³ê²½í ìë ììµëë¤.
setTimeout(() => user.sayHi(), 1000); // Hello, John!
ì´ë ê² ì½ë를 ìì±íë©´ ê°ê²°í´ì ¸ì 보기ë ì¢ì§ë§, ì½ê°ì ì·¨ì½ì±ì´ ìê¹ëë¤.
setTimeoutì´ í¸ë¦¬ê±° ë기 ì ì(1ì´ê° ì§ë기 ì ì) userê° ë³ê²½ëë©´, ë³ê²½ë ê°ì²´ì ë©ìë를 í¸ì¶íê² ë©ëë¤.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
setTimeout(() => user.sayHi(), 1000);
// 1ì´ê° ì§ë기 ì ì userì ê°ì´ ë°ë
user = { sayHi() { alert("ë ë¤ë¥¸ ì¬ì©ì!"); } };
// setTimeoutì ë ë¤ë¥¸ ì¬ì©ì!
ë ë²ì§¸ ë°©ë²ì ì¬ì©íë©´ ì´ë° ì¼ì´ ë°ìíì§ ììµëë¤.
ë°©ë² 2: bind
모ë í¨ìë this를 ìì íê² í´ì£¼ë ë´ì¥ ë©ìë bind를 ì ê³µí©ëë¤.
기본 문ë²ì ë¤ìê³¼ ê°ìµëë¤.
// ë ë³µì¡í 문ë²ì ë¤ì ëìµëë¤.
let boundFunc = func.bind(context);
func.bind(context)ë í¨ìì²ë¼ í¸ì¶ ê°ë¥í 'í¹ì ê°ì²´(exotic object)'를 ë°íí©ëë¤. ì´ ê°ì²´ë¥¼ í¸ì¶íë©´ thisê° contextë¡ ê³ ì ë í¨ì funcê° ë°íë©ëë¤.
ë°ë¼ì boundFunc를 í¸ì¶íë©´ thisê° ê³ ì ë func를 í¸ì¶íë ê²ê³¼ ëì¼í í¨ê³¼ë¥¼ ë´
ëë¤.
ìë funcUserìë thisê° userë¡ ê³ ì ë funcì´ í ë¹ë©ëë¤.
let user = {
firstName: "John"
};
function func() {
alert(this.firstName);
}
let funcUser = func.bind(user);
funcUser(); // John
ì¬ê¸°ì func.bind(user)ë funcì this를 userë¡ 'ë°ì¸ë©í ë³íâì´ë¼ê³ ìê°íìë©´ ë©ëë¤.
ì¸ìë ì본 í¨ì funcì âê·¸ëë¡â ì ë¬ë©ëë¤.
let user = {
firstName: "John"
};
function func(phrase) {
alert(phrase + ', ' + this.firstName);
}
// this를 userë¡ ë°ì¸ë©í©ëë¤.
let funcUser = func.bind(user);
funcUser("Hello"); // Hello, John (ì¸ì "Hello"ê° ë겨ì§ê³ thisë userë¡ ê³ ì ë©ëë¤.)
ì´ì ê°ì²´ ë©ìëì bind를 ì ì©í´ ë´
ìë¤.
let user = {
firstName: "John",
sayHi() {
alert(`Hello, ${this.firstName}!`);
}
};
let sayHi = user.sayHi.bind(user); // (*)
// ì´ì ê°ì²´ ìì´ë ê°ì²´ ë©ìë를 í¸ì¶í ì ììµëë¤.
sayHi(); // Hello, John!
setTimeout(sayHi, 1000); // Hello, John!
// 1ì´ ì´ë´ì user ê°ì´ ë³íí´ë
// sayHië 기존 ê°ì ì¬ì©í©ëë¤.
user = {
sayHi() { alert("ë ë¤ë¥¸ ì¬ì©ì!"); }
};
(*)ë¡ íìí ì¤ìì ë©ìë user.sayHi를 ê°ì ¸ì¤ê³ , ë©ìëì user를 ë°ì¸ë©í©ëë¤. sayHië ì´ì â묶ì¸(bound)â í¨ìê° ëì´ ë¨ë
ì¼ë¡ í¸ì¶í ì ìê³ setTimeoutì ì ë¬íì¬ í¸ì¶í ìë ììµëë¤. ì´ë¤ ë°©ìì´ë 컨íì¤í¸ë ìíë ëë¡ ê³ ì ë©ëë¤.
ìë ìì를 ì¤ííë©´ ì¸ìë âê·¸ëë¡â ì ë¬ëê³ bindì ìí´ thisë§ ê³ ì ë ê²ì íì¸í ì ììµëë¤.
let user = {
firstName: "John",
say(phrase) {
alert(`${phrase}, ${this.firstName}!`);
}
};
let say = user.say.bind(user);
say("Hello"); // Hello, John (ì¸ì "Hello"ê° sayë¡ ì ë¬ëììµëë¤.)
say("Bye"); // Bye, John ("Bye"ê° sayë¡ ì ë¬ëììµëë¤.)
bindAllë¡ ë©ìë ì ì²´ ë°ì¸ë©í기ê°ì²´ì ë³µìì ë©ìëê° ìê³ ì´ ë©ìë ì 체를 ì ë¬íë ¤ í ë, ë°ë³µë¬¸ì ì¬ì©í´ ë©ìë를 ë°ì¸ë©í ì ììµëë¤.
for (let key in user) {
if (typeof user[key] == 'function') {
user[key] = user[key].bind(user);
}
}
ìë°ì¤í¬ë¦½í¸ ë¼ì´ë¸ë¬ë¦¬ë¥¼ ì¬ì©í´ë ëê·ëª¨ ë°ì¸ë©ì í ì ììµëë¤. lodash ë¼ì´ë¸ë¬ë¦¬ì _.bindAll(object, methodNames)ì´ ê·¸ ìì ëë¤.
ë¶ë¶ ì ì©
ì§ê¸ê¹ì§ this ë°ì¸ë©ì ëí´ìë§ ì´ì¼ê¸°í´ë³´ììµëë¤. í ë¨ê³ ë ëìê° ë´
ìë¤.
this ë¿ë§ ìëë¼ ì¸ìë ë°ì¸ë©ì´ ê°ë¥í©ëë¤. ì¸ì ë°ì¸ë©ì ì ì°ì´ì§ ìì§ë§ ê°ë ì ì©í ëê° ììµëë¤.
bindì ì ì²´ 문ë²ì ë¤ìê³¼ ê°ìµëë¤.
let bound = func.bind(context, [arg1], [arg2], ...);
bindë 컨í
ì¤í¸ë¥¼ thisë¡ ê³ ì íë ê² ë¿ë§ ìëë¼ í¨ìì ì¸ìë ê³ ì í´ì¤ëë¤.
ê³±ì
ì í´ì£¼ë í¨ì mul(a, b)를 ììë¡ ë¤ì´ë³´ê² ìµëë¤.
function mul(a, b) {
return a * b;
}
bind를 ì¬ì©í´ ìë¡ì´ í¨ì doubleì ë§ë¤ê² ìµëë¤.
function mul(a, b) {
return a * b;
}
let double = mul.bind(null, 2);
alert( double(3) ); // = mul(2, 3) = 6
alert( double(4) ); // = mul(2, 4) = 8
alert( double(5) ); // = mul(2, 5) = 10
mul.bind(null, 2)를 í¸ì¶íë©´ ìë¡ì´ í¨ì doubleì´ ë§ë¤ì´ì§ëë¤. doubleì 컨í
ì¤í¸ê° null, 첫 ë²ì§¸ ì¸ìë 2ì¸ mulì í¸ì¶ ê²°ê³¼ê° ì ë¬ë©ëë¤. ì¶ê° ì¸ìë âê·¸ëë¡â ì ë¬ë©ëë¤.
ì´ë° ë°©ìì ë¶ë¶ ì ì©(partial application)ì´ë¼ê³ ë¶ë¦ ëë¤. ë¶ë¶ ì ì©ì ì¬ì©íë©´ 기존 í¨ìì 매ê°ë³ì를 ê³ ì íì¬ ìë¡ì´ í¨ì를 ë§ë¤ ì ììµëë¤.
ì ìììì this를 ì¬ì©íì§ ììë¤ë ì ì 주목íì기 ë°ëëë¤. bindì 컨í
ì¤í¸ë¥¼ íì ë겨ì¤ì¼ íë¯ë¡ nullì ì¬ì©íìµëë¤.
ë¶ë¶ ì ì©ì ì¬ì©í´ 3ì ê³±í´ì£¼ë í¨ì tripleì ë§ë¤ì´ë³´ê² ìµëë¤.
function mul(a, b) {
return a * b;
}
let triple = mul.bind(null, 3);
alert( triple(3) ); // = mul(3, 3) = 9
alert( triple(4) ); // = mul(3, 4) = 12
alert( triple(5) ); // = mul(3, 5) = 15
ê·¸ë°ë° ë¶ë¶ í¨ìë ì ë§ëë 걸ê¹ì?
ê°ë
ì±ì´ ì¢ì ì´ë¦(double, triple)ì ê°ì§ ë
립 í¨ì를 ë§ë¤ ì ìë¤ë ì´ì ë문ì
ëë¤. ê²ë¤ê° bind를 ì¬ì©í´ 첫 ë²ì§¸ ì¸ì를 ê³ ì í ì ì기 ë문ì ë§¤ë² ì¸ì를 ì ë¬í íìë ìì´ì§ì£ .
ì´ ì¸ìë ë¶ë¶ ì ì©ì ë§¤ì° í¬ê´ì ì¸ í¨ì를 기ë°ì¼ë¡ ë í¬ê´ì ì¸ ë³í í¨ì를 ë§ë¤ì ìë¤ë ì ìì ì ì©í©ëë¤.
í¨ì send(from, to, text)ê° ìë¤ê³ ê°ì í´ ë´
ìë¤. ê°ì²´ user ììì ë¶ë¶ ì ì©ì íì©íë©´, ì ì¡ ì£¼ì²´ê° íì¬ ì¬ì©ìì¸ í¨ì sendTo(to, text)를 구íí ì ììµëë¤.
컨í ì¤í¸ ìë ë¶ë¶ ì ì©
ì¸ì ì¼ë¶ë ê³ ì íê³ ì»¨í
ì¤í¸ thisë ê³ ì íê³ ì¶ì§ ìë¤ë©´ ì´ë»ê² í´ì¼ í ê¹ì?
ë¤ì´í°ë¸ bindë§ì¼ë¡ë 컨í
ì¤í¸ë¥¼ ìëµíê³ ì¸ìë¡ ë°ë¡ ë°ì´ëì§ ëª»í©ëë¤.
ë¤ííë ì¸ìë§ ë°ì¸ë©í´ì£¼ë í¬í¼ í¨ì partial를 구ííë ê±´ ì½ìµëë¤.
ìëì ê°ì´ ë§ì´ì£ .
function partial(func, ...argsBound) {
return function(...args) { // (*)
return func.call(this, ...argsBound, ...args);
}
}
// ì¬ì©ë²:
let user = {
firstName: "John",
say(time, phrase) {
alert(`[${time}] ${this.firstName}: ${phrase}!`);
}
};
// ìê°ì ê³ ì í ë¶ë¶ ë©ìë를 ì¶ê°í¨
user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
user.sayNow("Hello");
// ì¶ë ¥ê° ìì:
// [10:00] John: Hello!
partial(func[, arg1, arg2...])ì í¸ì¶íë©´ ëí¼((*))ê° ë°íë©ëë¤. ëí¼ë¥¼ í¸ì¶íë©´ funcì´ ë¤ìê³¼ ê°ì ë°©ìì¼ë¡ ëìí©ëë¤.
- ëì¼í
this를 ë°ìµëë¤(user.sayNowëuser를 ëìì¼ë¡ í¸ì¶ë©ëë¤). partialì í¸ì¶í ë ë°ì ì¸ì("10:00")ë...argsBoundì ì ë¬ë©ëë¤.- ëí¼ì ì ë¬ë ì¸ì(
"Hello")ë...argsê° ë©ëë¤.
ì ê° êµ¬ë¬¸ ëë¶ì ì´ ëª¨ë ê³¼ì ì´ ì¬ìì¡ìµëë¤.
lodash ë¼ì´ë¸ë¬ë¦¬ì _.partialì ì¬ì©íë©´ 컨í ì¤í¸ ìë ë¶ë¶ ì ì©ì ì§ì 구ííì§ ììë ë©ëë¤.
ìì½
func.bind(context, ...args)ë thisê° contextë¡ ê³ ì ëê³ ì¸ìë ê³ ì ë í¨ì funcì ë°íí©ëë¤.
bindë ë³´íµ ê°ì²´ ë©ìëì this를 ê³ ì í´ ì´ëê°ì ëê¸°ê³ ì í ë ì¬ì©í©ëë¤. setTimeoutì ë길 ë ê°ì´ ë§ì´ì£ .
기존 í¨ìì ì¸ì ëª ê°ë¥¼ ê³ ì í í¨ì를 ë¶ë¶ ì ì©(partially applied) í¨ì ëë ë¶ë¶(partial) í¨ìë¼ê³ ë¶ë¦ ëë¤.
ë¶ë¶ ì ì©ì ê°ì ì¸ì를 ì¬ë¬ ë² ë°ë³µíê³ ì¶ì§ ìì ë ì ì©í©ëë¤. send(from, to)ë¼ë í¨ìê° ìëë° fromì ê³ ì íê³ ì¶ë¤ë©´ send(from, to)ì ë¶ë¶ í¨ì를 구íí´ ì¬ì©íë©´ ë©ëë¤.
ëê¸
<code>í그를, ì¬ë¬ ì¤ë¡ 구ì±ë ì½ë를 ì½ì íê³ ì¶ë¤ë©´<pre>í그를 ì´ì©íì¸ì. 10ì¤ ì´ìì ì½ëë plnkr, JSBin, codepen ë±ì ìëë°ì¤ë¥¼ ì¬ì©íì¸ì.