자바스크립트 this, 7개의 예제로 이해해버리기!

자바스크립트의 this는 '호출자', 실행 문맥' 을 가리킵니다. 7개의 예제를 통해서 this를 뽀개보도록 하겠습니다.

예제 1.

console.log(this === window);

그냥 this를 호출하면 이는 window 객체가 됩니다.

예제 2.

function test1() {
    console.log(this === window);
}
test1();

함수에서도 this를 호출하면 window 객체입니다.

예제 3.

function test1() {
    'use strict'
    console.log(this === undefined);
}
test1();

strict 모드의 함수에서는 this가 undefined 입니다.

예제 4.

function test1() {
    'use strict'
    function test1_inner() {
        console.log(this === undefined)
    }
    test1_inner();
}
test1();

strict 모드일 경우 내부 scope에서도 this 는 undefined로 동일하게 적용됩니다.

예제 5.

var person = {
    name: 'NoDoudt',
    age: 30,
    introduce: function() {
        console.log(this === person);
        function fake_age() {
            console.log(this === window);
            return this.age - 5;
        }
        return ''.concat('내 이름은 ', this.name, ', 나이는 ', fake_age(), '이죠');
    }
}
person.introduce();
// 내 이름은 NoDoudt, 나이는 NaN이죠.

fake_age() 안에 있는 this는 객체 내부에서의 this라 person 객체를 가르킨다고 생각하기 쉽지요. 하지만 window를 가르킵니다.

우리가 생각하는 대로 this가 person 객체를 가르키도록 하려면 아래와 같이 해야 합니다.

var person = {
    name: 'NoDoudt',
    age: 30,
    introduce: function() {
        console.log(this === person);
        function fake_age() {
            console.log(this === person);
            return this.age - 5;
        }
        return ''.concat('내 이름은 ', this.name, ', 나이는 ', fake_age.call(this), '이죠');
    }
}
person.introduce();
// 내 이름은 NoDoudt, 나이는 25이죠.

예제 6.

function Person(name, age) {
    console.log(this instanceof Person); // Person 타입임을 확인
    this.name = name;
    this.age = age;
}
Person.prototype.introduce = function() {
    console.log(this instanceof Person); // Person 타입임을 확인
    return ''.concat('내 이름은 ', this.name, ', 나이는 ', this.age, '이죠');
}

var p1 = new Person('NoDoudt', 30);
p1.introduce();
// 내 이름은 NoDoudt, 나이는 30이죠.
class Person {
    constructor(name, age) {
        console.log(this instanceof Person); // Person 타입임을 확인
        this.name = name;
        this.age = age;
    }

    introduce() {
        console.log(this instanceof Person); // Person 타입임을 확인
           return ''.concat('내 이름은 ', this.name, ', 나이는 ', this.age, '이죠');
    }
}

var p1 = new Person('NoDoudt', 30);
p1.introduce();
// 내 이름은 NoDoudt, 나이는 30이죠.

생성자에서의 this는 새롭게 만들어진 객체를 나타냅니다.

예제 7.

function Person(name, age, nickname) {
    console.log(this instanceof Person); // Person 타입임을 확인
    this.name = name;
    this.age = age;
    this.nickname = nickname;
}
Person.prototype.introduce = function() {
    console.log(this instanceof Person); // Person 타입임을 확인

    this.nickname.map(function(value, index) {
       console.log(this === window); // this는 window.
       console.log(''.concat('내 이름은 ', this.name, '(', this.age,'). ', '근데 친구들이 ', value, '라고 자꾸 놀려..ㅠㅠ'));

    });
}
var p1 = new Person('NoDoudt', 30, ['바보', '머저리', '센쩍하는 양아치']);
p1.introduce();
// 내 이름은 (undefined). 근데 친구들이 바보라고 자꾸 놀려..ㅠㅠ
// 내 이름은 (undefined). 근데 친구들이 머저리라고 자꾸 놀려..ㅠㅠ
// 내 이름은 (undefined). 근데 친구들이 센쩍하는 양아치라고 자꾸 놀려..ㅠㅠ

map 안에서 this는 non-strict 모드에서 window이고, strict 모드에선 undefined 입니다. 위 예에선 this가 window 이기 때문에 this.name은 undefined가 나왔네요.

우리가 생각한 대로 동작하도록 고치려면,

(1) map 의 파라미터로 들어가는 함수에 bind(this)를 추가로 호출해주는 것입니다.

...
    console.log(this instanceof Person); // Person 타입임을 확인

    this.nickname.map(function(value, index) {
       console.log(this instanceof Person); // Person 타입임을 확인
       console.log(''.concat('내 이름은 ', this.name, '(', this.age,'). ', '근데 친구들이 ', value, '라고 자꾸 놀려..ㅠㅠ'));

    }.bind(this) );

...

var p1 = new Person('NoDoudt', 30, ['바보', '머저리', '센쩍하는 양아치']);
p1.introduce();
// 내 이름은 NoDoudt(30). 근데 친구들이 바보라고 자꾸 놀려..ㅠㅠ
// 내 이름은 NoDoudt(30). 근데 친구들이 머저리라고 자꾸 놀려..ㅠㅠ
// 내 이름은 NoDoudt(30). 근데 친구들이 센쩍하는 양아치라고 자꾸 놀려..ㅠㅠ

(2) map 함수에 array function을 사용하는 것입니다.

...
    console.log(this instanceof Person); // Person 타입임을 확인

    this.nickname.map((value, index) => {
       console.log(this instanceof Person); // Person 타입임을 확인
       console.log(''.concat('내 이름은 ', this.name, '(', this.age,'). ', '근데 친구들이 ', value, '라고 자꾸 놀려..ㅠㅠ'));

    });
...

var p1 = new Person('NoDoudt', 30, ['바보', '머저리', '센쩍하는 양아치']);
p1.introduce();
// 내 이름은 NoDoudt(30). 근데 친구들이 바보라고 자꾸 놀려..ㅠㅠ
// 내 이름은 NoDoudt(30). 근데 친구들이 머저리라고 자꾸 놀려..ㅠㅠ
// 내 이름은 NoDoudt(30). 근데 친구들이 센쩍하는 양아치라고 자꾸 놀려..ㅠㅠ

레퍼런스: 링크1, 링크2

댓글

Designed by JB FACTORY