[NodeJS] Named function, arrow function this 바인딩

Onam Kwon·2023년 5월 31일
0

Node JS

목록 보기
25/25

Named function, arrow function this 바인딩

function regular() {
	console.log('This is a regular function.');
}
regular(); // This is a regular function.

const arrow = () => {
	console.log('This is an arrow function.');
}
arrow() // This is an arrow function.
  • 위와 같이 JavaScript 에는 일반 함수와 화살표 함수가 존재하며 둘은 사실 약간의 차이가 존재합니다.
  • 이는 아래와 같습니다.
/**
 * When a named function is called as a standalone function,
 * the `this` value inside the function refers to the global object(`window` in a browser environment).
 * Or `undefined` in certain cases.
 */
function greet() {
    console.log('greet():', this);
    console.log();
}
greet(); // global object
  • 위는 named function 이라고 부르며 일반적이고 정통적인 형태를 가진 함수입니다.
  • named function은 위처럼 독립적인 함수 형태로 호출이 된다면 this값은 global object값을 가집니다.
    • 여기서 독립적인 함수 형태란 메소드 형태가 아닌 함수 원형으로 호출되는 방식을 말하며 greeet()과 같은 호출 방식을 말합니다. 이 경우, this값은 global object를 가집니다.
  • 반대로 메소드란 객체에 달려있는 함수로서 person.greet()와 같은 객체의 메소드를 호출하는 방식을 말합니다. 이 경우, this값은 자동으로 해당 객체에 바인딩 됩니다.
/**
 * When a named function is called as a method of an object,
 * the `this` value inside the function is bound to the object itself.
 */
const person = {
    name: 'John',
    greet: function() {
        // 일반 함수가 메소드 형태로 호출 될 때 `this` 값은 자동으로 해당 객체에 바인딩 됩니다. 따라서 John을 갖습니다.
        console.log('person.greet():', this.name); // John
      
        // 하지만 아래는 독립적으로 실행되는 함수로 `this`값은 위의 예시와 같이 `global object` 를 갖지만 
        // `global object`는 `name` 프로퍼티를 가지고 있지 않으므로 undefined 값을 가집니다. 
        const namedFunction = function() {
            console.log('namedFunction():', this.name);
        }
        // `this` value is pointing at the global object but since there is no `name` property, the result would be undefined.
        namedFunction(); // undefined, 

        /**
        * Arrow functions do not have their own `this` binding.
        * Instead, they inherit the `this` value from the surrounding(lexical) scope where they are defined.
        */
        // 화살표 함수는 자체적으로 `this`값을 가지고 있지 않기 때문에
        // 가장 가까운 상위 개체의 `this`값을 상속받습니다. (person 객체).
        const arrowFunction = () => {
            console.log('arrowFunction():', this.name); // John
        }
        arrowFunction();
    }
}
person.greet();
person.greet(): John
namedFunction(): undefined
arrowFunction(): John
  • 위의 코드에는 person 객체가 있으며 해당 객체는 greet() 메소드를 가지고 있습니다.
    • 해당 메소는 처음에 바로 this.name 값을 출력합니다.
      • 이때 해당 함수는 person.greet() 를 통해 호출되므로 메소드 형식으로 호출되었습니다. 따라서 첫번째 this값은 person 객체에 자동으로 바인딩 되므로 John을 출력합니다.
    • 이어서 namedFunction() 함수를 호출합니다.
      • 해당 함수는 standalone 함수로 독립적으로 호출된 함수입니다. 따라서 this값은 전역 객체를 가리키지만 전역 객체는 name 속성을 가지고 있지 않으므로 undefined값을 출력합니다.
    • 마지막으로 arrowFunction() 함수를 호출합니다.
      • 해당 함수는 화살표 함수이며 화살표 함수는 this값을 가지고 있지 않습니다. 하지만 가장 가까운 상위 객체의 this 값을 상속받으므로 이 경우 person 객체가 되며 John을 출력할 수 있습니다.
// strict-mode.

/**
 * In strict mode, when a named function is called as a standalone function.
 * the `this` value inside the function is set to `undefined`.
 * This prevents the default binding of `this` to the global object.
 */
function strictModeGreet() {
    'use strict';
    console.log('strictModeGreet():', this);
    console.log();
}
strictModeGreet(); // undefined
  • 지금까지 non-strict mode인 경우에 대해 알아보았고 위 경우는 strict mode를 사용했을 때 입니다.
  • strict mode에서 함수를 호출한다면 this값은 전역 객체가 아닌 undefined를 가리킵니다.
  • 따라서 함수의 타입과 호출 방식, 그리고 strict mode의 여부에 따라 this값이 달라짐을 확인할 수 있습니다. 이를 정리하자면 아래와 같습니다.

Named functions

Non-Strict Mode

  • named function이 독립적으로 호출되면(i.e., 메소드 형식으로 호출되지 않으면), 함수 내부의 this값은 global object값을 가리킵니다(브라우저의 경우 windonw 객체). 또는 JavaScript 환경에 따라서 undefined.
  • named function이 메소드 형태로 호출되면(i.e., object.method()), 함수 내부의 this값은 해당 객체에 자동으로 바인딩 됩니다. this값은 함수 호출의 맥락에 따라 런타임에 동적으로 결정됩니다.

Strict Mode

  • strict mode에서 named function이 독립적으로 호출되면, 함수 내부의 this값은 undefined값을 가집니다.
  • 이는 this값의 디폴트 바인딩이 global object를 가리키는걸 예방해 줍니다.

Arrow functions

Non-Strict Mode and Strict Mode

  • arrow function은 자신의 this 값을 가지지 않습니다. 대신에 가장 가까운 상위 렉시컬 범위에서 이 값을 상속받습니다. 이를 lexical scoping 이라고 부릅니다.
  • 함수 내부의 this값은 화살표 함수가 어떻게 호출되는지 또는 어디에서 호출되는지에 따라 변경되지에 영향을 받지 않습니다.

github

profile
권오남 / Onam Kwon

0개의 댓글