JavaScript 기본 상식 #3 (scope에 따른 this)

JavaScript 기본 상식 #3 (scope에 따른 this)

JavaScript에서 "this"는 생각보다 복잡한 상황을 초래한다.
어떻게 보면 왜 그랬을까 싶기도 한데, 상황에 따른 복잡한 문제가 있는데, 모두 다룰 순 없고, 여기에서는, 익숙해지는 정도까지 진행해보고자 한다.

일반적으로 "this"는 scope는 "{}"에 기반한다고 이해하는 것이 보통은 편하다.

console.log('What is this?, this);

결과는? (Chrome DevTools console)
What is this? Window

여기 "Window"는 우리가 알고 있는 그 window이다. 그럼, 함수 내에서는 어떻게 표현되는지 확인해 보자!
this.foo = 'window';
console.log('[Window Scope] What is foo?', this, this.foo);
(function test1() {
    console.log('[Function Scope:Previous] What is foo?', this, this.foo);
    this.foo = 'global';
    console.log('[Function Scope] What is foo?', this, this.foo);
    return {
        foo: 'local',
        bar: function () {
            console.log('[Function Scope:Inner] What is foo?', this, this.foo);
        }
    };
})().bar();

결과는? (Chrome DevTools console)
[Window Scope] What is foo? Window window
[Function Scope:Previous] What is foo? Window window
[Function Scope] What is foo? Window global
[Function Scope:Inner] What is foo? {foo: "local", bar: f} local

ES6 이후의 새로 추가된 "arrow function" 및 shorthand 로도 함수를 선언할 수 있는데, 그 결과는 확연히 달라집니다.
즉, shorthand에 해당하는 선언은 "arrow function"의 짧은 선언이 아니란 것입니다.
bar: function () {
}

bar() {
}
는 this에 대응하는 방식이 동일합니다. 하지만, arrow function"은 다릅니다.
bar: () => {
}

즉, "key: function name() {}" = "key() {}" ≒ "key: () => {}"*) 이렇게 이해해야 합니다.
(function test2() {
    this.foo = 2;
    const obj1 = {
        foo: 3,
        bar: function () {
            return this.foo;
        }
    };
    const obj2 = {
        foo: 4,
        bar() {
            return this.foo;
        }
    };
    const obj3 = {
        foo: 5,
        bar: () => {
            return this.foo;
        }
    };
    console.log('obj1', obj1.foo, obj1.bar(), 'done');
    console.log('obj2', obj2.foo, obj2.bar(), 'done');
    console.log('obj3', obj3.foo, obj3.bar(), 'done');
    console.log('binded obj1', obj1.foo, obj1.bar.call({foo: 9}), 'done');
    console.log('binded obj2', obj2.foo, obj2.bar.call({foo: 9}), 'done');
    console.log('binded obj3', obj3.foo, obj3.bar.call({foo: 9}), 'done');
})()


obj1 3 3 done
obj2 4 4 done
obj3 5 2 done
binded obj1 3 9 done
binded obj2 4 9 done
binded obj3 5 2 done <= 변화 없음
}

"binded obj1"과 "binded obj2"는 값이 모두 바뀐 것을 확인할 수 있다. 그러나, "binded obj3"은 바뀌지 않았다는 것을 볼 수 있다.
즉, object내에서 선언할 때는, 1)과 같이 이해하면 될 것이다.

댓글

이 블로그의 인기 게시물

Next.js에서 자연스러운 Page Transition 방법

[flutter] Android - Package간 sdk version 등이 맞지 않아 오류가 발생하는 경우

[Windows] Chocolatey upgrade