🐯 What is 'this' in JavaScript?

BoriΒ·2022λ…„ 3μ›” 26일
6
post-thumbnail

thisλž€?

λ‹€λ₯Έ λŒ€λΆ€λΆ„μ˜ 객체지ν–₯ μ–Έμ–΄μ—μ„œμ˜ this

  • 클래슀둜 μƒμ„±ν•œ μΈμŠ€ν„΄μŠ€ 객체
    β‡’ ν΄λž˜μŠ€μ—μ„œλ§Œ μ‚¬μš©

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ this

  • μ–΄λ””μ„œλ“  μ‚¬μš©ν•  수 있고, 상황에 따라 thisκ°€ λ°”λΌλ³΄λŠ” λŒ€μƒμ΄ 달라진닀.
    β‡’ this의 μž‘λ™ 방식을 μ΄ν•΄ν•˜μ§€ λͺ»ν•˜λ©΄ λ¬Έμ œκ°€ λ°œμƒν–ˆμ„ λ•Œ 원인을 μ°Ύμ•„ ν•΄κ²°ν•˜κΈ° μ–΄λ ΅λ‹€.

  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” ν•¨μˆ˜μ™€ 객체(λ©”μ„œλ“œ)의 ꡬ뢄이 λŠμŠ¨ν•˜λ‹€.
    β‡’ thisκ°€ 이 λ‘˜μ„ κ΅¬λΆ„ν•˜λŠ” μœ μΌν•œ κΈ°λŠ₯

상황에 따라 λ‹¬λΌμ§€λŠ” this

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ thisλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 생성될 λ•Œ κ²°μ •

  • ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄?
    • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ μƒμ„±λœλ‹€.
    • thisκ°€ κ²°μ •λœλ‹€.

β‡’ ν•¨μˆ˜λ₯Ό μ–΄λ–€ λ°©μ‹μœΌλ‘œ ν˜ΈμΆœν•˜λŠλƒμ— 따라 this 값이 달라진닀.

μ „μ—­ κ³΅κ°„μ—μ„œμ˜ this β‡’ 전역객체!

  • κ°œλ…μƒ μ „μ—­ μ»¨ν…μŠ€νŠΈλ₯Ό μƒμ„±ν•˜λŠ” 주체 === 전역객체
    • λΈŒλΌμš°μ € ν™˜κ²½μ—μ„œμ˜ 전역객체 : window
    • Node.js ν™˜κ²½μ—μ„œμ˜ 전역객체 : global

예제 3-1, 3-2) μ „μ—­ κ³΅κ°„μ—μ„œμ˜ this

// λΈŒλΌμš°μ € ν™˜κ²½
console.log(this); // Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
console.log(window); // Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}
console.log(this === window); // true

// Node.js ν™˜κ²½
console.log(this); // Object [global] {...}
console.log(global); // Object [global] {...}
console.log(this === window); // true

λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•  λ•Œ κ·Έ λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œμ˜ this

ν•¨μˆ˜ μ‹€ν–‰ν•˜λŠ” 방법

  • ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•˜λŠ” 경우
  • λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•˜λŠ” 경우

ν•¨μˆ˜ vs λ©”μ„œλ“œ

  • 미리 μ •μ˜ν•œ λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” μ½”λ“œ λ­‰μΉ˜
  • ν•¨μˆ˜μ™€ λ©”μ„œλ“œλ₯Ό κ΅¬λΆ„ν•˜λŠ” μœ μΌν•œ 차이 β‡’ 독립성
  • ν•¨μˆ˜ : 독립적인 κΈ°λŠ₯을 μˆ˜ν–‰
  • λ©”μ„œλ“œ : μžμ‹ μ„ ν˜ΈμΆœν•œ λŒ€μƒ 객체에 κ΄€ν•œ λ™μž‘μ„ μˆ˜ν–‰

β‡’ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μƒν™©λ³„λ‘œ this ν‚€μ›Œλ“œμ— λ‹€λ₯Έ 값을 λΆ€μ—¬ν•˜κ²Œ ν•¨μœΌλ‘œμ¨ 이λ₯Ό κ΅¬ν˜„

"λ©”μ„œλ“œλŠ” 객체의 ν”„λ‘œνΌν‹°μ— ν• λ‹Ήλœ ν•¨μˆ˜μΌκΉŒμš”?"
= λ°˜λ§žλ°˜ν‹€!

  • ν•¨μˆ˜λ₯Ό 객체의 ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•œλ‹€κ³  ν•΄μ„œ κ·Έ μžμ²΄λ‘œμ„œ 무쑰건 λ©”μ„œλ“œκ°€ λ˜λŠ” 것은 μ•„λ‹ˆλ‹€.
  • 객체의 λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•˜λŠ” κ²½μš°μ—λŠ” λ©”μ„œλ“œλ‘œ λ™μž‘, 그렇지 μ•ŠμœΌλ©΄ ν•¨μˆ˜λ‘œ λ™μž‘ν•œλ‹€.

예제 3-6) ν•¨μˆ˜λ‘œμ„œ 호좜, λ©”μ„œλ“œλ‘œμ„œ 호좜

// λ³€μˆ˜ func에 읡λͺ…ν•¨μˆ˜ ν• λ‹Ή
var func = function (x) {
  console.log(this, x);
};

func(1); // Window { ... } 1 전역객체 좜λ ₯

// λ³€μˆ˜ obj에 객체 ν• λ‹Ή
var obj = {
  // 객체의 method ν”„λ‘œνΌν‹°μ— func ν•¨μˆ˜ ν• λ‹Ή
  method: func
};

obj.method(2); // {method: Ζ’} 2

β‡’ λ³€μˆ˜μ— λ‹΄μ•„ ν˜ΈμΆœν•œ κ²½μš°μ™€ 객체의 ν”„λ‘œνΌν‹°μ— ν• λ‹Ήν•΄μ„œ ν˜ΈμΆœν•œ 경우 thisκ°€ 달라진닀.

'ν•¨μˆ˜λ‘œμ„œ 호좜'κ³Ό 'λ©”μ„œλ“œλ‘œμ„œ 호좜'을 μ–΄λ–»κ²Œ κ΅¬λΆ„ν• κΉŒ?

  • ν•¨μˆ˜ μ•žμ— 점(.)의 μ—¬λΆ€λ‘œ ꡬ뢄 : 점 ν‘œκΈ°λ²•, λŒ€κ΄„ν˜Έ ν‘œκΈ°λ²•
  • ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ κ·Έ ν•¨μˆ˜ 이름(ν”„λ‘œνΌν‹°λͺ…) μ•žμ— 객체가 λͺ…μ‹œλ˜μ–΄ μžˆλŠ” 경우 = λ©”μ„œλ“œλ‘œ 호좜
  • 그렇지 μ•Šμ€ λͺ¨λ“  경우 = ν•¨μˆ˜λ‘œ 호좜

예제 3-7) λ©”μ„œλ“œλ‘œμ„œ 호좜 - 점 ν‘œκΈ°λ²•, λŒ€κ΄„ν˜Έ ν‘œκΈ°λ²•

var obj = {
    method: function (x) { console.log(this, x); }
};

obj.method(1); // {method: Ζ’} 1
obj.['method'](2); // {method: Ζ’} 2

λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œμ˜ this

thisμ—λŠ” ν˜ΈμΆœν•œ 주체에 λŒ€ν•œ 정보가 λ‹΄κΈ΄λ‹€.

  • ν•¨μˆ˜λ₯Ό λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•˜λŠ” 경우 호좜 주체 = ν•¨μˆ˜λͺ…(ν”„λ‘œνΌν‹°λͺ…) μ•žμ˜ 객체
  • 점 ν‘œκΈ°λ²•μ˜ 경우 λ§ˆμ§€λ§‰ 점 μ•žμ— λͺ…μ‹œλœ 객체 = this

예제 3-8) λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œμ˜ this

var obj = {
    methodA: function (x) { console.log(this); },
    inner: {
        methodB: function (x) { console.log(this); },
    }
};

obj.methodA(); // {inner: {…}, methodA: Ζ’} ( === obj )
obj.inner.methodB(); // {methodB: Ζ’} ( === obj.inner )

ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  λ•Œ κ·Έ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ this

ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ this

  • ν•¨μˆ˜λ₯Ό ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  경우 thisλŠ” μ§€μ •λ˜μ§€ μ•ŠλŠ”λ‹€.
    • ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•˜λŠ” 것 = 호좜 주체(객체지ν–₯ μ–Έμ–΄μ—μ„œμ˜ 객체)λ₯Ό λͺ…μ‹œν•˜μ§€ μ•Šκ³ , κ°œλ°œμžκ°€ μ½”λ“œμ— 직접 κ΄€μ—¬ν•΄μ„œ μ‹€ν–‰ν•œ 것
    • 호좜 주체의 정보λ₯Ό μ•Œ 수 μ—†λ‹€.
  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό ν™œμ„±ν™”ν•  λ‹Ήμ‹œμ— thisκ°€ μ§€μ •λ˜μ§€ μ•Šμ€ 경우, thisλŠ” μ „μ—­ 객체λ₯Ό 바라본닀.
    β‡’ ν•¨μˆ˜μ—μ„œμ˜ thisλŠ” μ „μ—­ 객체λ₯Ό 바라본닀.

λ©”μ„œλ“œμ˜ λ‚΄λΆ€ν•¨μˆ˜μ—μ„œμ˜ this

  • ν•¨μˆ˜λ₯Ό λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•  λ•Œμ™€ ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•  λ•Œ thisκ°€ 무엇을 κ°€λ¦¬ν‚€λŠ”μ§€ μ•Œκ³  μžˆλ‹€.
    β‡’ λ‚΄λΆ€ν•¨μˆ˜ λ˜ν•œ 이λ₯Ό λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν–ˆλŠ”μ§€ λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν–ˆλŠ”μ§€λ§Œ νŒŒμ•…ν•˜λ©΄ this의 값을 μ•Œ 수 μžˆλ‹€.

예제 3-9) λ‚΄λΆ€ν•¨μˆ˜μ—μ„œμ˜ this

// obj1 객체 생성
var obj1 = {
    // obj1 객체 λ‚΄λΆ€μ˜ outer ν”„λ‘œνΌν‹°μ— 읡λͺ…ν•¨μˆ˜ μ—°κ²°
    outer: function () {
        console.log('outer', this); // obj1 객체 정보가 좜λ ₯
        
        // innerFuncλŠ” outer μŠ€μ½”ν”„μ—μ„œλ§Œ μ ‘κ·Όν•  수 μžˆλŠ” μ§€μ—­λ³€μˆ˜
        var innerFunc = function() {
            console.log('innerFunc', this); // Window 객체 정보가 좜λ ₯
        }
        
        // innerFunc 호좜
        innerFunc();
        
        // obj2λŠ” outer μŠ€μ½”ν”„μ—μ„œλ§Œ μ ‘κ·Όν•  수 μžˆλŠ” μ§€μ—­λ³€μˆ˜
        // λ‹€μ‹œ 객체 ν• λ‹Ή
        var obj2 = {
            // obj2 객체 λ‚΄λΆ€μ˜ innerMethod ν”„λ‘œνΌν‹°μ— innerFunc와 μ—°κ²°λœ 읡λͺ…ν•¨μˆ˜ μ—°κ²°
            innerMethod: innerFunc
        };
        
        // obj2.innerMethod 호좜
        obj2.innerMethod(); // obj2 객체 정보가 좜λ ₯
    }
};

// obj1.outer 호좜
obj1.outer();
  • obj1.outer 호좜

    • obj1.outer ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성, ν˜Έμ΄μŠ€νŒ…, μŠ€μ½”ν”„ 체인 정보 μˆ˜μ§‘, this 바인딩
    • 이 ν•¨μˆ˜λŠ” ν˜ΈμΆœν•  λ•Œ ν•¨μˆ˜λͺ…인 outer μ•žμ— 점(.)이 μžˆμ—ˆμœΌλ―€λ‘œ λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•œ 것
    • λ”°λΌμ„œ, thisμ—λŠ” λ§ˆμ§€λ§‰ 점 μ•žμ˜ 객체인 obj1이 바인딩
  • innerFunc 호좜

    • innerFunc ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성, ν˜Έμ΄μŠ€νŒ…, μŠ€μ½”ν”„ 체인 정보 μˆ˜μ§‘, this 바인딩
    • 이 ν•¨μˆ˜λŠ” ν˜ΈμΆœν•  λ•Œ ν•¨μˆ˜λͺ… μ•žμ— 점(.)이 μ—†μœΌλ―€λ‘œ ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•œ 것
    • thisκ°€ μ§€μ •λ˜μ§€ μ•Šμ•˜μœΌλ―€λ‘œ μžλ™μœΌλ‘œ μŠ€μ½”ν”„ μ²΄μΈμƒμ˜ μ΅œμƒμœ„ 객체인 전역객체(window) 바인딩
  • obj2.innerMethod 호좜

    • obj2.innerMethod ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성
    • 이 ν•¨μˆ˜λŠ” ν˜ΈμΆœν•  λ•Œ ν•¨μˆ˜λͺ…인 innerMethod μ•žμ— 점(.)이 μžˆμ—ˆμœΌλ―€λ‘œ λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•œ 것
    • λ”°λΌμ„œ, thisμ—λŠ” λ§ˆμ§€λ§‰ 점 μ•žμ˜ 객체인 obj2κ°€ 바인딩
  • innerFunc 호좜과 obj2.innerMethod 호좜

    • 같은 ν•¨μˆ˜μž„μ—λ„ λ°”μΈλ”©λ˜λŠ” this의 λŒ€μƒμ΄ μ„œλ‘œ λ‹€λ₯΄λ‹€.

β‡’ this 바인딩은 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λŠ” λ‹Ήμ‹œμ˜ μ£Όλ³€ ν™˜κ²½(λ©”μ„œλ“œ 내뢀인지, ν•¨μˆ˜ 내뢀인지 λ“±)은 μ€‘μš”ν•˜μ§€ μ•Šκ³ , ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” ꡬ문 μ•žμ— 점 λ˜λŠ” λŒ€κ΄„ν˜Έ ν‘œκΈ°μ˜ μ—¬λΆ€κ°€ μ€‘μš”

예제 3-9 좜λ ₯ κ²°κ³Ό)

호좜 주체가 없을 λ•ŒλŠ” μžλ™μœΌλ‘œ 전역객체λ₯Ό λ°”μΈλ”©ν•˜μ§€μ•Šκ³ , 호좜 λ‹Ήμ‹œ μ£Όλ³€ ν™˜κ²½μ˜ thisλ₯Ό κ·ΈλŒ€λ‘œ 상속받아 μ‚¬μš©ν•  수 μžˆλ‹€λ©΄?

  • λ³€μˆ˜λ₯Ό κ²€μƒ‰ν•˜λ©΄ μš°μ„  κ°€μž₯ κ°€κΉŒμš΄ μŠ€μ½”ν”„μ˜ L.Eλ₯Ό μ°Ύκ³ , μ—†λ‹€λ©΄ μƒμœ„ μŠ€μ½”ν”„λ₯Ό νƒμƒ‰ν•œλ‹€.
  • this도 ν˜„μž¬ μ»¨ν…μŠ€νŠΈμ— λ°”μΈλ”©λœ λŒ€μƒμ΄ μ—†μœΌλ©΄ 직전 μ»¨ν…μŠ€νŠΈμ˜ thisλ₯Ό 바라보도둝 ν•  수 μ—†μ„κΉŒ?

β‡’ ES5κΉŒμ§€λŠ” 자체적으둜 λ‚΄λΆ€ν•¨μˆ˜μ— thisλ₯Ό 상속할 방법은 μ—†μœΌλ‚˜ μš°νšŒν•˜λŠ” 방법은 μžˆλ‹€.

λ©”μ„œλ“œμ˜ λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œμ˜ thisλ₯Ό μš°νšŒν•˜λŠ” 방법

예제 3-10) λ‚΄λΆ€ν•¨μˆ˜μ—μ„œμ˜ thisλ₯Ό μš°νšŒν•˜λŠ” 방법 - λ³€μˆ˜ ν™œμš©

  • λ³€μˆ˜μ— μƒμœ„ μŠ€μ½”ν”„μ˜thisλ₯Ό μ €μž₯ν•΄μ„œ λ‚΄λΆ€ν•¨μˆ˜μ—μ„œ ν™œμš©
var obj = {
    outer: function () {
        console.log('outer', this); // obj 객체 정보가 좜λ ₯
        
        var innerFunc1 = function() {
            console.log('innerFunc1', this); // Window 객체 정보가 좜λ ₯
        }
        
        innerFunc1();
        
        // outer μŠ€μ½”ν”„μ—μ„œ selfλΌλŠ” λ³€μˆ˜μ— thisλ₯Ό μ €μž₯
        var self = this;
        var innerFunc2 = function() {
            console.log('innerFunc2', self); // obj 객체 정보가 좜λ ₯
        }
        
        innerFunc2();
    }
};

obj.outer();

예제 3-10 좜λ ₯ κ²°κ³Ό)

thisλ₯Ό λ°”μΈλ”©ν•˜μ§€ μ•ŠλŠ” ν•¨μˆ˜

  • ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ thisκ°€ 전역객체λ₯Ό λ°”λΌλ³΄λŠ” 문제λ₯Ό λ³΄μ™„ν•˜κΈ° μœ„ν•΄, ES6μ—μ„œλŠ” thisλ₯Ό λ°”μΈλ”©ν•˜μ§€ μ•ŠλŠ” ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό λ„μž…
  • ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό 생성할 λ•Œ this 바인딩 과정이 빠짐
    β‡’ μƒμœ„ μŠ€μ½”ν”„μ˜ thisλ₯Ό κ·ΈλŒ€λ‘œ ν™œμš© κ°€λŠ₯
  • λ‚΄λΆ€ν•¨μˆ˜λ₯Ό ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ λ°”κΎΈλ©΄ λ³€μˆ˜λ₯Ό ν™œμš©ν•œ this μš°νšŒλ²•μ΄ λΆˆν•„μš”ν•˜λ‹€.
    (ES5 ν™˜κ²½μ—μ„œλŠ” ν™”μ‚΄ν‘œν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μ—†μŒ)

예제 3-11) thisλ₯Ό λ°”μΈλ”©ν•˜μ§€ μ•ŠλŠ” ν•¨μˆ˜(ν™”μ‚΄ν‘œ ν•¨μˆ˜)

var obj = {
    outer: function () {
        console.log(this); // {outer: Ζ’}
        
        var innerFunc = () => {
            console.log(this); // {outer: Ζ’}
        };
        
        innerFunc();
    }
};

obj.outer();

예제 3-11 좜λ ₯ κ²°κ³Ό)

콜백 ν•¨μˆ˜ 호좜 μ‹œ κ·Έ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ this

  • 콜백 ν•¨μˆ˜ : ν•¨μˆ˜ A의 μ œμ–΄κΆŒμ„ λ‹€λ₯Έ ν•¨μˆ˜(λ˜λŠ” λ©”μ„œλ“œ) Bμ—κ²Œ λ„˜κ²¨μ£ΌλŠ” 경우, ν•¨μˆ˜ Aλ₯Ό 콜백 ν•¨μˆ˜λΌκ³  ν•œλ‹€.
    β‡’ ν•¨μˆ˜ AλŠ” ν•¨μˆ˜ B의 λ‚΄λΆ€ λ‘œμ§μ— 따라 μ‹€ν–‰
    β‡’ this μ—­μ‹œ ν•¨μˆ˜ B λ‚΄λΆ€ λ‘œμ§μ—μ„œ μ •ν•œ κ·œμΉ™μ— 따라 값이 κ²°μ •
콜백 ν•¨μˆ˜λ„ ν•¨μˆ˜μ΄λ―€λ‘œ 기본적으둜 thisκ°€ 전역객체λ₯Ό μ°Έμ‘°ν•˜μ§€λ§Œ, μ œμ–΄κΆŒμ„ 받은 ν•¨μˆ˜μ—μ„œ 콜백 ν•¨μˆ˜μ— λ³„λ„λ‘œ thisκ°€ 될 λŒ€μƒμ„ μ§€μ •ν•œ 경우 κ·Έ λŒ€μƒμ„ μ°Έμ‘°

콜백 ν•¨μˆ˜μ—μ„œμ˜ this의 μ˜ˆμ œλŠ” 콜백 ν•¨μˆ˜: μ œμ–΄κΆŒ - this 예제 4-6에 정리해 λ‘μ—ˆμŠ΅λ‹ˆλ‹€.

  • 콜백 ν•¨μˆ˜μ˜ μ œμ–΄κΆŒμ„ κ°€μ§€λŠ” ν•¨μˆ˜(λ©”μ„œλ“œ)κ°€ 콜백 ν•¨μˆ˜μ—μ„œμ˜ thisλ₯Ό λ¬΄μ—‡μœΌλ‘œ 할지 κ²°μ •
  • νŠΉλ³„νžˆ μ •μ˜ν•˜μ§€ μ•Šμ€ 경우, 전역객체λ₯Ό μ°Έμ‘°

μƒμ„±μž ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ this

  • μƒμ„±μž ν•¨μˆ˜ : μ–΄λ–€ κ³΅ν†΅λœ μ„±μ§ˆμ„ μ§€λ‹ˆλŠ” 객체듀을 μƒμ„±ν•˜λŠ” 데 μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜
  • 객체 지ν–₯ μ–Έμ–΄μ—μ„œ
    • μƒμ„±μž = 클래슀(class)
    • 클래슀λ₯Ό 톡해 λ§Œλ“  객체 = μΈμŠ€ν„΄μŠ€(instance)
  • μƒμ„±μžλŠ” ꡬ체적인 μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€κΈ° μœ„ν•œ μΌμ’…μ˜ ν‹€
    β‡’ ν•΄λ‹Ή 클래슀의 곡톡 속성듀이 미리 μ€€λΉ„λ˜μ–΄ 있고, 여기에 ꡬ체적인 μΈμŠ€ν„΄μŠ€μ˜ κ°œμ„±μ„ 더해 κ°œλ³„ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.
  • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν•¨μˆ˜μ— μƒμ„±μžλ‘œμ„œμ˜ 역할을 ν•¨κ»˜ λΆ€μ—¬
  • new λͺ…λ Ήμ–΄λ‘œ ν•¨μˆ˜λ₯Ό 호좜
    β‡’ ν•΄λ‹Ή ν•¨μˆ˜κ°€ μƒμ„±μžλ‘œμ„œ λ™μž‘
    β‡’ 생성사 ν•¨μˆ˜λ‘œμ„œ 호좜 된 경우, λ‚΄λΆ€μ—μ„œμ˜ thisλŠ” 곧 μƒˆλ‘œ λ§Œλ“€ ꡬ체적인 μΈμŠ€ν„΄μŠ€ μžμ‹ μ΄ λœλ‹€.

예제 3-13) μƒμ„±μž ν•¨μˆ˜

// λ³€μˆ˜ Cat에 읡λͺ… ν•¨μˆ˜ ν• λ‹Ή
var Cat = function (name, age) {
    // ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this둜 μ ‘κ·Ό 
    // bark, name, age ν”„λ‘œνΌν‹°μ— 각각 값을 λŒ€μž…
    this.bark = 'μ•Όμ˜Ή';
    this.name = name;
    this.age = age;
};

var choco = new Cat('μ΄ˆμ½”', 7);
var nabi = new Cat('λ‚˜λΉ„', 5);

console.log(choco, nabi); // 각각 Cat 클래슀의 μΈμŠ€ν„΄μŠ€ 객체가 좜λ ₯

예제 3-13 좜λ ₯ κ²°κ³Ό)

λͺ…μ‹œμ μœΌλ‘œ thisλ₯Ό λ°”μΈλ”©ν•˜λŠ” 방법

  • 상황에 따라 this에 바인딩 λ˜λŠ” κ°’μ˜ κ·œμΉ™μ΄ 쑴재
    β‡’ μ΄λŸ¬ν•œ κ·œμΉ™μ„ κΉ¨κ³  this에 λ³„λ„μ˜ λŒ€μƒμ„ 바인딩 ν•˜λŠ” 방법도 쑴재

call λ©”μ„œλ“œ

Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])

μž„μ˜μ˜ 객체λ₯Ό this둜 지정 κ°€λŠ₯

  • λ©”μ„œλ“œμ˜ 호좜 주체인 ν•¨μˆ˜λ₯Ό μ¦‰μ‹œ μ‹€ν–‰
  • 첫 번째 인자(=thisArg)λ₯Ό this에 바인딩
  • 이 ν›„μ˜ μΈμžλ“€(arg1, arg2, ...)은 ν˜ΈμΆœν•  ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜

예제 3-14) call λ©”μ„œλ“œ

// ν•¨μˆ˜.call λ©”μ„œλ“œ
var func = function (a, b, c) {
    console.log('func: ', this, a, b, c)
}

func(1, 2, 3); // func: Window { ... } 1 2 3
func.call({ x:1 }, 4, 5, 6); // func: {x: 1} 4 5 6

// 객체의 λ©”μ„œλ“œ.call λ©”μ„œλ“œ
// λ©”μ„œλ“œμ— λŒ€ν•΄μ„œλ„ μž„μ˜μ˜ 객체λ₯Ό this둜 지정 κ°€λŠ₯
var obj = {
    a: 1,
    method: function (x, y) {
        console.log('obj.method: ', this.a, x, y);
    }
}

obj.method(2, 3); // obj.method: 1 2 3
obj.method.call({ a: 4 }, 5, 6); // obj.method: 4 5 6

예제 3-14 좜λ ₯ κ²°κ³Ό)

apply λ©”μ„œλ“œ

Function.prototype.apply(thisArg[, argsArray])
  • call λ©”μ„œλ“œμ™€ κΈ°λŠ₯적으둜 동일
  • 두 번째 인자λ₯Ό λ°°μ—΄λ‘œ λ°›μ•„ κ·Έ λ°°μ—΄μ˜ μš”μ†Œλ“€μ„ ν˜ΈμΆœν•  ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜λ‘œ 지정

예제 3-16) apply λ©”μ„œλ“œ

// ν•¨μˆ˜.apply λ©”μ„œλ“œ
var func = function (a, b, c) {
    console.log('func: ', this, a, b, c)
}

func.apply({ x:1 }, [4, 5, 6]); // func: {x: 1} 4 5 6

// 객체의 λ©”μ„œλ“œ.apply λ©”μ„œλ“œ
var obj = {
    a: 1,
    method: function (x, y) {
        console.log('obj.method: ', this.a, x, y);
    }
}

obj.method.apply({ a: 4 }, [5, 6]); // obj.method: 4 5 6

예제 3-16 좜λ ₯ κ²°κ³Ό)

call / apply λ©”μ„œλ“œμ˜ ν™œμš©μ‚¬λ‘€

μœ μ‚¬λ°°μ—΄κ°μ²΄(array-like object)에 λ°°μ—΄ λ©”μ„œλ“œλ₯Ό 적용

μœ μ‚¬λ°°μ—΄κ°μ²΄ : ν‚€κ°€ 0 λ˜λŠ” μ–‘μ˜ μ •μˆ˜μΈ ν”„λ‘œνΌν‹°κ°€ μ‘΄μž¬ν•˜κ³  length ν”„λ‘œνΌν‹°μ˜ 값이 0 λ˜λŠ” μ–‘μ˜ μ •μˆ˜μΈ 객체, λ°°μ—΄μ˜ ꡬ쑰와 μœ μ‚¬ν•œ 객체
  • κ°μ²΄μ—λŠ” λ°°μ—΄ λ©”μ„œλ“œλ₯Ό 직접 μ μš©ν•  수 μ—†λ‹€.
  • μœ μ‚¬λ°°μ—΄κ°μ²΄μ˜ 경우 call / apply λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄ λͺ¨λ“  λ°°μ—΄ λ©”μ„œλ“œ 적용 κ°€λŠ₯
  • ES6μ—μ„œλŠ” μœ μ‚¬λ°°μ—΄ 객체 λ˜λŠ” 순회 κ°€λŠ₯ν•œ λͺ¨λ“  μ’…λ₯˜μ˜ 데이터 νƒ€μž…μ„ λ°°μ—΄λ‘œ μ „ν™˜ν•˜λŠ” Array.fromλ©”μ„œλ“œλ₯Ό λ„μž…

μƒμ„±μž λ‚΄λΆ€μ—μ„œ λ‹€λ₯Έ μƒμ„±μžλ₯Ό 호좜

  • μƒμ„±μž 내뢀에 λ‹€λ₯Έ μƒμ„±μžμ™€ κ³΅ν†΅λœ λ‚΄μš©μ΄ μžˆμ„ 경우, call / apply λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄ λ‹€λ₯Έ μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜μ—¬ λ°˜λ³΅μ„ 쀄일 수 μžˆλ‹€.

μ—¬λŸ¬ 인수λ₯Ό λ¬Άμ–΄ ν•˜λ‚˜μ˜ λ°°μ—΄λ‘œ μ „λ‹¬ν•˜κ³  싢을 λ•Œ - apply ν™œμš©

  • μ—¬λŸ¬ 개의 인수λ₯Ό λ°›λŠ” λ©”μ„œλ“œμ— ν•˜λ‚˜μ˜ λ°°μ—΄λ‘œ 인수λ₯Ό 전달할 λ•Œ apply λ©”μ„œλ“œ μ‚¬μš©

예제 3-23) call / apply λ©”μ„œλ“œμ˜ ν™œμš© - Math.max /Max.min 에 apply 적용

var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min); // 45 3

β‡’ call / apply λ©”μ„œλ“œλŠ” λͺ…μ‹œμ μœΌλ‘œ λ³„λ„μ˜ thisλ₯Ό λ°”μΈλ”©ν•˜λ©΄μ„œ ν•¨μˆ˜ λ˜λŠ” λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜λŠ” 쒋은 λ°©λ²•μ΄μ§€λ§Œ 였히렀 thisλ₯Ό μ˜ˆμΈ‘ν•˜κΈ° 어렀움
(ES5 μ΄ν•˜μ˜ ν™˜κ²½μ—μ„œλŠ” λ‹€λ₯Έ λŒ€μ•ˆμ΄ μ—†μœΌλ―€λ‘œ μ‹€λ¬΄μ—μ„œ κ΄‘λ²”μœ„ν•˜κ²Œ ν™œμš©)

bind λ©”μ„œλ“œ

Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
  • ES5μ—μ„œ μΆ”κ°€λœ κΈ°λŠ₯
  • callκ³Ό λΉ„μŠ·ν•˜μ§€λ§Œ μ¦‰μ‹œ ν˜ΈμΆœν•˜μ§€ μ•Šκ³ , λ„˜κ²¨ 받은 this 및 μΈμˆ˜λ“€μ„ λ°”νƒ•μœΌλ‘œ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ°˜ν™˜
  • μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ 인수λ₯Ό λ„˜κΈ°λ©΄ κ·Έ μΈμˆ˜λ“€μ€ κΈ°μ‘΄ bind λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ μ „λ‹¬ν–ˆλ˜ μΈμˆ˜λ“€μ˜ 뒀에 μ΄μ–΄μ„œ λ“±λ‘λœλ‹€.
  • bind λ©”μ„œλ“œμ˜ λͺ©μ 
    • ν•¨μˆ˜μ— thisλ₯Ό 미리 μ μš©ν•˜λŠ” 것
    • λΆ€λΆ„ 적용 ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λŠ” 것

예제 3-25) bind λ©”μ„œλ“œ - this 지정과 λΆ€λΆ„ 적용 ν•¨μˆ˜ κ΅¬ν˜„

var func = function (a, b, c, d) {
    console.log(this, a, b, c, d);
};

func(1, 2, 3, 4); // Window{ ... } 1 2 3 4

// λ³€μˆ˜ bindFunc1에 func에 thisλ₯Ό { x: 1 }둜 μ§€μ •ν•œ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό μ„ μ–Έ
var bindFunc1 = func.bind({ x:1 });
bindFunc1(5, 6, 7, 8); // {x: 1} 5 6 7 8

// λ³€μˆ˜ bindFunc2에 func에 thisλ₯Ό { x: 1 }둜 지정 
// μ•žμ—μ„œλΆ€ν„° 두 개의 인수둜 각각 4, 5둜 μ§€μ •ν•œ μƒˆλ‘œμš΄ ν•¨μˆ˜ μ„ μ–Έ
var bindFunc2 = func.bind({ x:1 }, 4, 5);
bindFunc2(6, 7); // {x: 1} 4 5 6 7
bindFunc2(8, 9); // {x: 1} 4 5 8 9
  • bindFunc1의 bind: this만 지정
  • bindFunc2의 bind: this 지정과 λΆ€λΆ„ 적용 ν•¨μˆ˜ κ΅¬ν˜„

name ν”„λ‘œνΌν‹°

  • bind λ©”μ„œλ“œλ₯Ό μ μš©ν•΄μ„œ μƒˆλ‘œ λ§Œλ“  ν•¨μˆ˜λŠ” name ν”„λ‘œνΌν‹°μ— 'bound'λΌλŠ” 접두어가 λΆ™μŒ
  • 원본 ν•¨μˆ˜μ— bind λ©”μ„œλ“œλ₯Ό μ μš©ν•œ μƒˆλ‘œμš΄ ν•¨μˆ˜λΌλŠ” μ˜λ―Έμ΄λ―€λ‘œ call / apply보닀 μ½”λ“œ 좔적이 μ‰¬μ›Œμ§„λ‹€.

예제 3-26) name ν”„λ‘œνΌν‹°

var func = function (a, b, c, d) {
    console.log(this, a, b, c, d);
};

var bindFunc = func.bind({ x:1 }, 4, 5);

console.log(func.name); // func
console.log(bindFunc.name); // bound func

예제 3-26 좜λ ₯ κ²°κ³Ό)

μƒμœ„ μ»¨ν…μŠ€νŠΈμ˜ thisλ₯Ό λ‚΄λΆ€ν•¨μˆ˜λ‚˜ 콜백 ν•¨μˆ˜μ— μ „λ‹¬ν•˜κΈ°

  • λ³€μˆ˜λ₯Ό ν™œμš©ν•œ λ‚΄λΆ€ν•¨μˆ˜μ—μ„œμ˜ thisλ₯Ό μš°νšŒν•˜λŠ” 방법
    β‡’ call, apply, bind λ©”μ„œλ“œ μ΄μš©ν•˜κΈ°

예제 3-27) λ‚΄λΆ€ν•¨μˆ˜μ— this 전달 - call, bind

// call λ©”μ„œλ“œ
var obj = {
    outer: function () {
        console.log(this);
        
        var innerFunc = function () {
            console.log(this);
        };
        
        innerFunc.call(this);
    }
};

obj.outer();

// bind λ©”μ„œλ“œ
var obj = {
    outer: function () {
        console.log(this);
        
        var innerFunc = function () {
            console.log(this);
        }.bind(this);
        
        innerFunc();
    }
};

obj.outer();

ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ μ˜ˆμ™Έμ‚¬ν•­

ν™”μ‚΄ν‘œ ν•¨μˆ˜

  • ES6μ—μ„œ μƒˆλ‘­κ²Œ λ„μž…
  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성 μ‹œ thisλ₯Ό λ°”μΈλ”©ν•˜λŠ” 과정이 μ œμ™Έ
    β‡’ ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—λŠ” thisκ°€ μ—†μœΌλ©°, μ ‘κ·Όν•˜κ³ μž ν•˜λ©΄ μŠ€μ½”ν”„μ²΄μΈμƒ κ°€μž₯ κ°€κΉŒμš΄ this에 μ ‘κ·Ό

예제 3-29) ν™”μ‚΄ν‘œ ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ this

  • 예제 3-27의 λ‚΄λΆ€ν•¨μˆ˜λ₯Ό ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ λ³€κ²½
    β‡’ λ³„λ„μ˜ λ³€μˆ˜λ‘œ thisλ₯Ό μš°νšŒν•˜κ±°λ‚˜ call, apply, bindλ₯Ό μ μš©ν•  ν•„μš”κ°€ μ—†λ‹€.
var obj = {
    outer: function () {
        console.log(this);
        
        var innerFunc = () => {
            console.log(this);
        };
        
        innerFunc();
    }
};

obj.outer();

예제 3-29 좜λ ₯ κ²°κ³Ό)

λ³„λ„μ˜ 인자둜 thisλ₯Ό λ°›λŠ” 경우 (콜백 ν•¨μˆ˜ λ‚΄μ—μ„œμ˜ this)

  • 콜백 ν•¨μˆ˜λ₯Ό 인자둜 λ°›λŠ” λ©”μ„œλ“œ 쀑 μΌλΆ€λŠ” μΆ”κ°€λ‘œ this둜 지정할 객체(thisArg)λ₯Ό 인자둜 지정할 수 μžˆλŠ” κ²½μš°κ°€ μžˆλ‹€.
    β‡’ thisArg 값을 μ§€μ •ν•˜λ©΄ 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ this 값을 μ›ν•˜λŠ” λŒ€λ‘œ λ³€κ²½ κ°€λŠ₯

예제 3-31) 콜백 ν•¨μˆ˜μ™€ ν•¨κ»˜ thisArgλ₯Ό 인자둜 λ°›λŠ” λ©”μ„œλ“œ

Array.prototype.forEach(callback[, thisArg])
Array.prototype.map(callback[, thisArg])
Array.prototype.filter(callback[, thisArg])
Array.prototype.some(callback[, thisArg])
Array.prototype.every(callback[, thisArg])
Array.prototype.find(callback[, thisArg])
Array.prototype.findIndex(callback[, thisArg])
Array.prototype.flatMap(callback[, thisArg])
Array.prototype.from(arrayLike[, callback[, thisArg]])
Set.prototype.forEach(callback[, thisArg])
Map.prototype.forEach(callback[, thisArg])

정리

λͺ…μ‹œμ  바인딩이 μ—†λŠ” 경우

  • μ „μ—­κ³΅κ°„μ—μ„œμ˜ thisλŠ” 전역객체λ₯Ό μ°Έμ‘°
  • ν•¨μˆ˜λ₯Ό λ©”μ„œλ“œλ‘œμ„œ ν˜ΈμΆœν•œ 경우, thisλŠ” λ©”μ„œλ“œ 호좜 주체(λ©”μ„œλ“œ λͺ… μ•žμ˜ 객체)λ₯Ό μ°Έμ‘°
  • ν•¨μˆ˜λ₯Ό ν•¨μˆ˜λ‘œμ„œ ν˜ΈμΆœν•œ 경우, thisλŠ” 전역객체 μ°Έμ‘° (λ©”μ„œλ“œμ˜ λ‚΄λΆ€ν•¨μˆ˜μ—μ„œλ„ 동일)
  • 콜백 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œμ˜ thisλŠ” ν•΄λ‹Ή 콜백 ν•¨μˆ˜μ˜ μ œμ–΄κΆŒμ„ λ„˜κ²¨λ°›μ€ ν•¨μˆ˜κ°€ μ •μ˜ν•œ 바에 λ”°λ₯΄λ©°, μ •μ˜ν•˜μ§€ μ•Šμ€ 경우 전역객체 μ°Έμ‘°
  • μƒμ„±μž ν•¨μˆ˜μ—μ„œμ˜ thisλŠ” 생성될 μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°

λͺ…μ‹œμ  this 바인딩

  • call, apply λ©”μ„œλ“œλŠ” thisλ₯Ό λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜λ©΄μ„œ ν•¨μˆ˜ λ˜λŠ” λ©”μ„œλ“œλ₯Ό 호좜
  • bind λ©”μ„œλ“œλŠ” this 및 ν•¨μˆ˜μ— λ„˜κΈΈ 인수λ₯Ό 일뢀 μ§€μ •ν•΄μ„œ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ§Œλ“¦
  • μš”μ†Œλ₯Ό μˆœνšŒν•˜λ©΄μ„œ 콜백 ν•¨μˆ˜λ₯Ό 반볡 ν˜ΈμΆœν•˜λŠ” λ‚΄μš©μ˜ 일뢀 λ©”μ„œλ“œλŠ” λ³„λ„μ˜ 인자둜 thisλ₯Ό 받기도 ν•œλ‹€.

μ°Έκ³ 

  • μ½”μ–΄ μžλ°”μŠ€ν¬λ¦½νŠΈ - 03_this

마무리

  • 이 전에 콜백 ν•¨μˆ˜μ— λŒ€ν•΄ μ •λ¦¬ν•œ 글을 올린 ν›„, μŠ€ν„°λ”” νŒ€μ›μ˜ this에 λŒ€ν•œ λ°œν‘œλ₯Ό λ“£κ²Œ λ˜μ—ˆλ‹€.
  • νŒ€μ›μ˜ λ°œν‘œκ°€ λ„ˆλ¬΄ μ’‹μ•˜λ‹€. 이해 쏙쏙-
    β‡’ λ‚˜λŠ” λ°œν‘œν•  λ•Œ 버벅거리고 λ°œν‘œ 쀑간에 진행이 λŠκΈ°κΈ°λ„ ν–ˆμ—ˆλŠ”λ° λ‚˜μ™€ λ‹€λ₯΄κ²Œ μŠ€λ¬΄μŠ€ν•œ 진행 λ„ˆλ¬΄ λ©‹μ Έ~
  • 콜백 ν•¨μˆ˜μ™€ μ—°κ²°λœ λ‚΄μš©λ“€μ΄ λ§Žμ•„ this에 λŒ€ν•΄ λ¨Όμ € 글을 μ˜¬λ €μ•Όκ² λ‹€ ν•˜κ³  λ‚΄μš© 정리λ₯Ό μ‹œμž‘ν–ˆλŠ”λ° 생각보닀 λ‚΄μš©μ΄ λ§Žμ•„μ„œ μ‹œκ°„μ΄ μ˜€λž˜κ±Έλ Έλ‹€.
    β‡’ 정리 μ™„λ£Œν•˜λ‹ˆκΉŒ 뿌!λ“―!

0개의 λŒ“κΈ€