Post

✅함수 호출 방식에 따른 This, 화살표 함수

this

this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다.

javascript에서 this는 어디서든지 참조 가능하다.

전역이나 일반 함수 내부에서 this는 전역객체인 window를 가리킨다.

1
2
3
4
5
6
console.log(this) // window

function square(number) {
  console.log(this) // window
  return number * number
}

함수 호출 방식

this가 가리키는 값은 함수 호출 방식에 의해 동적으로 결정된다.

바인딩이란 식별자와 값을 연결하는 과정을 의미한다. 예를 들어, 변수 선언은 변수 식별자와 확보된 메모리 공간의 주소를 바인딩하는 것이다. this 바인딩은 this(식별자)와 this가 가리킬 객체를 바인딩하는 것이다.

함수를 호출하는 방식에는 다음이 있다.

  • 일반 함수 호출
  • 메서드 호출
  • 생성자 함수 호출
  • Function.prototype.apply/call/bind 메서드에 의한 간접 호출

함수로서 호출, 메서드로서 호출

어떤 함수를 객체의 프로퍼티에 할당한다고 해서 그 자체로서 메서드가 되는 것이 아니라 객체의 메서드로서 호출한 경우에만 메서드로 동작하고, 그렇지 않으면 함수로 동작한다.

일반 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행한다.

함수로서 호출과 메서드로서 호출은 함수 앞에 .의 여부로 구분한다.

어떤 함수를 메서드로서 호출하는 경우 this는 바로 함수명(프로퍼티명) . 앞의 객체이다.

1
2
3
4
5
6
7
8
9
const func = function () {
  console.log(this)
}
func() // window

const obj = {
  method: func
}
obj.method() // {method: f}

메서드 내부 함수에서의 this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const obj1 = {
  outer: function () {
    console.log(this)
    const innerFunc = function () {
      console.log(this)
    }
    innerFunc() // window

    const obj2 = {
      innerMethod: innerFunc
    }
    obj2.innerMethod() // obj2
  }
}
obj.outer() // obj1
  • obj.outer() : outer 앞에 .이 있으므로 메서드로서 호출한 것. 따라서 this에는 점 앞의 객체인 obj1이 바인딩된다.
  • innerFunc() : innerFunc 앞에 .이 붙지 않았으므로 일반 함수로서 호출한 것. 따라서 자동으로 스코프 체인상 최상위 객체인 window가 바인딩된다.
  • obj2.innerMethod() : innerMethod 앞에 .이 있으므로 메서드로서 호출한 것. 따라서 this에는 점 앞의 객체인 obj2이 바인딩된다.

생성자 함수 내부에서의 this

함수가 생성자 함수로서 호출된 경우 내부에서의 this는 자신이 생성할 인스턴스를 가리킨다.

new 명령어로 생성자 함수를 호출하면 생성자의 prototype 프로퍼티를 참조하는 __proto__라는 프로퍼티가 있는 객체(인스턴스)를 만들고, 속성을 해당 this에 부여한다.

1
2
3
4
5
6
7
8
9
10
11
const Cat = function (name, age) {
  this.bark = '야옹'
  this.name = name
  this.age = age
}

const choco = new Cat('초코', 7)
const nabi = new Cat('나비', 5)
console.log(choco, nabi)
// Cat {bark: '야옹', name: '초코', age: 7}
// Cat {bark: '야옹', name: '나비', age: 5}

화살표 함수 (arrow function)

ES6에서 일반 함수 내부의 this가 전역객체를 바라보는 문제를 보완하기 위해 화살표 함수를 도입했다.

화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠지게 되어 상위 스코프의 this를 그대로 활용할 수 있다.

메서드 내부 함수에서의 this와 비교하면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const obj1 = {
  outer: function () {
    const innerFunc = function () {
      console.log(this) // window
    }
    innerFunc()
  }
}

const obj2 = {
  outer: function () {
    const innerFunc = () => {
      console.log(this) // {outer: f}
    }
    innerFunc()
  }
}

객체의 메서드로 사용하면

화살표 함수는 자신의 this가 없다.

대신 화살표 함수를 둘러싸는 렉시컬 스코프의 this가 사용된다.

1
2
3
4
5
6
7
8
9
10
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 {...}

때문에 스코프를 생성하지 않는 객체의 메서드에서 this는 전역객체를 가리킨다.

기타

화살표 함수는 생성자로서 사용될 수 없으며 new와 함께 사용하면 오류가 발생한다.

1
2
var Foo = () => {}
var foo = new Foo() // TypeError: Foo is not a constructor

화살표 함수는 prototype 속성이 없다.

1
2
var Foo = () => {}
console.log(Foo.prototype) // undefined

참고사이트

화살표 함수

This post is licensed under CC BY 4.0 by the author.