This is This

November 07, 2021

Q. This에 대해서 설명해주세요.

  • 사전적 의미 : 이것, 어떠한것을 지칭하는 말
  • 자바스크립트에서의 의미: 호출한 실행환경(Execution Context)을 나타내는것
  • 멀티 쓰레드일 경우 (ex. 스칼라도 자바스크립트와 비슷하다)
    • callback을 호출 → 어떤 thread로 실행이 되는것인가? → 그건 실행환경에 따라 달라진다
    • 기본적으로 global(window)에서 호출된다.

1. 자바스크립트에서의 this

  • 해당 함수를 호출한 실행 컨텍스트(코드가 실행되는 곳)을 가리킨다. (런타임에 결정)

    const test = {
        prop: 42,
        func: function () {
            return this.prop
        },
    }
    
    console.log(test.func())
    // expected output: 42
  • 단, new 키워드를 만나면, 해당 함수의 this는 생성자를 가르킨다.

    function Product(name, price) {
        this.name = name
        this.price = price
    }
    
    const cheese = new Product('feta', 5)
  • defaults : window (node환경: global)

  • strick-mode에서는 this === 'undefined'

2. this의 정확한 의미

  • 다른 언어(Java, Swift, 정적언어...?)

    • 생성되는 인스턴스를 가르킨다.
    //java
    public class Foo {
    		public String name;
        public String color;
    
        public Fruit(String name, String color) {
            this.name = name;
    				this.color = color;
        }
    }
    
    // swift
    class Bar {
      let row: Int, column: Int
    
      init(row: Int, column: Int) {
        self.row = row
        self.column = column
      }
    }
  • js

    • es6부터 Class 문법(사실은 함수...)을 지원하기 때문에, 위 언어와 비슷하게 동작한다.
    • babel을 활용하여, transpilering 해보면, 아래와 같이 this를 활용하여 호출하게 된다(링크)
    class Foo {
        constructor(name) {
            this.name = name
        }
    
        foo() {
            console.log(this.name)
        }
    }
    
    // babel Compile
    // this
    var Foo = /*#__PURE__*/ (function () {
        function Foo(name) {
            _classCallCheck(this, Foo)
    
            this.name = name
        }
    
        _createClass(Foo, [
            {
                key: 'foo',
                value: function foo() {
                    console.log(this.name)
                },
            },
        ])
    
        return Foo
    })()

3. call, apply, bind

  • 정적바인딩 : bind

    • bind는 this가 지정된 함수를 리턴한다.

    • bind된 함수는 다시 bind 할 수 없다.

      const foo = {
          bar: 1,
          hello() {
              console.log(this.bar)
          },
      }
      // 전역변수
      bar = 2
      
      foo.hello()
      const a = foo.hello.bind(this)
  • 동적바인딩(default) : call, apply

    • call, apply는 this를 할당한 함수의 실행결과 를 리턴한다.

      // call
      function say(phrase) {
          alert(this.name + ': ' + phrase)
      }
      
      let user = { name: 'John' }
      
      // this엔 user가 고정되고, "Hello"는 메서드의 첫 번째 인수가 됩니다.
      say.call(user, 'Hello') // John: Hello
      
      // apply
      const numbers = [5, 6, 2, 3, 7]
      
      const max = Math.max.apply(null, numbers)
  • decorator 만들기

    • 함수의 역할은 그대로 두고, 기능을 더해준다 (데코레이터 패턴)

      function work(a, b) {
          console.log(a + b)
      }
      
      function spy(func) {
          return function (...arg) {
              return func.apply(this, arg)
          }
      }
      
      work = spy(work)
      
      work(1, 2) // 3
      work(4, 5) // 9

4. 화살표 함수, 일반 함수의 차이

  • 일반 함수

    - this 호출한 컨텍스트
    - arguments 객체를 이용하여, 모든 인자를 받을 수 있음
    - new 키워드를 사용할 수 있음
  • 화살표 함수

    - this 렉시컬 컨텍스트 (선언될때, 이미 this가 할당)
    - arguments 객체가 없음..
    - new 키워드를 사용하여 호출 할 수 없음

5. event handler의 this

// html
<button id="foo">FOO</button>

<button>
	<span id="bar">BAR</span>
</button>

$foo.addEventListener('click', function () {
  console.log('function this', this)   // <button id="foo">FOO</button>
})

$foo.addEventListener('click', () => {
  console.log('arrow function this', this) // window
})

$bar.addEventListener('click', function () {
  console.log('function this', this) // <span id="bar">BAR</span>
})

© 2023, Customized by Joon