티스토리 뷰

JavaScript

this

ljy98 2022. 1. 10. 14:58

1. 소개

2. this를 이용하는 함수 실행에 대한 4가지 방식

    2.1. 일반 함수 실행 방식 (Regular Function Call)

    2.2. 도트 표기법 (Dot Notation)

    2.3. 명백한 바인딩 (Explicit Binding) / call, bind, apply

    2.4. new 키워드를 사용한 함수 실행


1. 소개

자바스크립트에는 this라는 키워드가 있다. this는 문맥에 따라서 다양한 값을 가지는데, this가 쓰이는 함수를 어떤 방식으로 실행하느냐에 따라서 그 역할이 구분된다. 

 

this의 값들은 크게 4가지 정도로 나뉜다. 즉, this를 이용하는 함수를 4가지 방식 중에서 어떤 방식으로 실행하느냐에 따라 this의 값이 결정된다는 뜻이다. 이러한 특성 때문에 this가 무엇을 지칭하는지 알기 위해서 this가 사용된 함수가 어디서 어떻게 실행되었는지를 알아야 한다.

 

2. this를 이용하는 함수 실행에 대한 4가지 방식

 

2.1. 일반 함수 실행 방식 (Regular Function Call)

첫 번째로, 일반 함수 실행 방식으로 함수를 실행했을 때 this의 값은 전역 객체(Global Object)를 가리킨다. 즉, 브라우저 상에서는 window 객체를 말한다. 일반 함수 실행 방식이란 아래 코드처럼 함수를 선언한 후, 실행할 때 흔히 사용하는 방식을 말한다.

function foo() {

    console.log(this);
    
}

foo();

위 코드에서 foo라는 함수를 선언하고, foo();라고 실행했다. 여기서 foo(); 와 같은 방식으로 함수를 호출하는 것을 일반 함수 실행 방식이라고 한다. 이 때, foo 함수 안에 있는 this는 전역 객체, 브라우저 상에서는 window 객체를 가리킨다.

 

var name = "henry";

function foo() {

    console.log(this.name); // 'henry'
    
}

foo();

위 코드에서 전연 변수로 name이란 변수를 만들고 'henry'라는 값을 할당했다. 이 변수는 전역 변수이기 때문에 전역 객체인 window에 속성으로 추가된다. 즉, var name = 'henry'; 라는 코드를 쓰면 window 객체에 name이라는 key와 'henry'라는 value가 추가된다.

 

이 때의 this는 window 객체를 가리키므로 위 코드의 console.log(this.name); 은 console.log(window.name); 이라고 한 것과 동일하다. 그러므로 위 코드를 실행시키면 콘솔 창에 'henry'가 출력된다.

 

var age = 26;

function foo() {

    var age = 25;
    
    bar(age);
    
}

function bar() {

    console.log(this.age);
    
}

foo();

위 코드에서 foo 함수 안에 bar 함수가 실행되고 있는데, bar 함수는 this.age를 콘솔창에 출력한다. 이 때, bar 함수는 foo 함수 내부에서 일반 함수 실행 방식으로 실행된다. bar 함수에 매개변수로 무엇을 넘겨주든 bar 함수 내부의 this.age는 window.age를 가리키고, 이는 전역 변수로 선언된 age 변수의 값을 말한다. 그러므로 위 코드 실행결과 25가 아닌 26이 출력된다.

 

 

※ strict mode에서 일반 함수 실행 방식 (Regular Function Call in Strict Mode)

strict mode란 단어 그대로 엄격한 형식이라는 뜻이다. 즉, strict mode에서 실행되는 모든 코드들에 좀 더 엄격한 규칙들을 적용하는 것을 말한다. strict mode를 사용하려면 스크립트 코드 최상단에 'use strict'; 혹은 "use strict"; 라는 구문을 추가하면 된다.

'use strict';

var name = 'henry';

function foo() {

    console.log(this.name); // error
    
}

foo();

보통 일반 함수 실행 방식에서 this는 window 객체를 가리킨다. 하지만 strict mode에서 this는 무조건 undefined이다. 그렇기 때문에 위 코드에서 this.name을 출력하면, foo 함수가 일반 함수 실행 방식으로 실행되었다고 해도 strict mode이기 때문에 this는 undefined가 된다. undefined에는 어떠한 속성도 없으므로 this.name은 실행할 수 없어 에러가 난다.

 

코드를 작성할 때 this가 실수로 window 객체로 인식되어 예상치 못한 에러가 발생하는 경우가 종종 나타나는데, strict mode는 그러한 버그의 발생을 처음부터 방지해준다.

 

2.2. 도트 표기법 (Dot Notation)

Dot Notation이란 Object를 만들고 그 Object의 key와 value를 부여한 후 도트(.)로 값에 접근하는 방식을 말한다.

var age = 26;

var henry = {

    age: 25,
    
    foo: function() {
    
        console.log(this.age); // 25
        
    }
    
}

henry.foo();

위 코드에서 henry라는 변수에 Object를 만들었다. 그리고 foo라는 key에 this.age를 출력하도록 함수를 만들었다. 함수를 실행하기 위해 henry.foo(); 처럼 도트를 사용하여 객체 속성의 값에 접근하는 방식을 Dot Notation이라고 한다.

 

이렇게 Dot Notation으로 함수가 실행되면, this는 그 도트 앞에 써있는 객체 자체를 가리킨다. 즉, 위 코드에서 this.age의 this는 henry를 가리킨다. this.age는 henry.age와 같기 때문에 25가 출력된다.

 

function foo() {

    console.log(this.age);
    
}

var age = 50;

var henry = {

    age: 25,
    
    foo: foo

}

var jenny = {

    age: 30,
    
    foo: foo
    
}

henry.foo(); // 25

jenny.foo(); // 30

var fn = henry.foo;

fn(); // 50

위 코드에서 foo라는 함수에는 this.age를 출력하는 실행문이 들어있다. 그리고 전역 변수 age가 선언되어 50이라는 값이 할당되었다. 그리고 henry라는 객체가 선언되어 age와 foo라는 key를 부여했고, foo라는 value는 함수 foo의 이름이다. jenny 또한 마찬가지이다.

 

이 상황에서 henry.foo();라고 함수를 실행하면 이때 foo 함수는 Dot Notation 방식으로 실행되기 때문에 this는 henry 객체 자체를 가리키게 되고 25라는 값이 출력된다. jenny.foo();도 마찬가지이다.

 

하지만 fn이라는 변수에 henry.foo라는 값을 입력하고 fn();이라고 실행한 것은 Dot Notation이 아닌 일반 함수 실행 방식이다. 그러므로 이 때 this는 Global Object를 가리키게 되고 전역 변수 age의 값인 50이 출력된다.

 

2.3. 명백한 바인딩 (Explicit Binding) / call, bind, apply

명백한 바인딩은 this의 역할을 명확하게 직접 지정해준다는 뜻이다. 이는 function.prototype.call, function.prototype.bind, function.prototype.apply와 같은 메소드와 함께 사용할 수 있다.

var age = 50;

function foo() {

    console.log(this.age);
    
}

var henry = {

    age: 30,
    
    log: foo
    
}

foo.call(henry, 1, 2, 3); // 30

위 코드에서 foo 함수에 call 메소드를 사용해 실행했고, 인자로 각각 henry, 1, 2, 3을 주었다. 이 인자들 중 가장 첫 번째로 쓴 henry가 this의 값으로 지정된다. 1, 2, 3은 this의 값과 상관없이 순서대로 foo 함수가 된다. 그러므로 this.age는 henry.age가 되어 30이 출력된다.

 

var age = 50;

function foo() {

    console.log(this.age);
    
}

var henry = {

    age: 35,
    
    log: foo
    
}

foo.apply(henry, [1, 2, 3, 4, 5]);

위 코드에서 apply 또한 같은 역할을 한다. apply는 this의 값을 지정해주는 인자 외에도 배열을 인자로 넣을 수 있는데, 이 배열의 값이 순차적으로 foo 함수의 인자가 된다.

 

2.4. new 키워드를 사용한 함수 실행

함수를 new 키워드를 사용해서 생성자 함수로 만들어 사용할 수 있다. 이 경우 this는 빈 객체가 된다.

function Person() {

    console.log(this);
    
}

new Person();

위 코드에서 Person이라는 함수를 선언했고, new 키워드를 사용하여 new Person(); 이라고 Person 함수를 생성자 함수로 사용했다. 이 때, this는 빈 객체를 가리키며 위의 생성자 함수는 this라는 빈 객체를 return한다. (return문이 없을 때에도 포함)

 

function Foo() {

    console.log(this.age); // undefined
    
    this.age = 50; // 빈 객체에 속성 추가
    
    console.log(this.age); // 50
    
}

new Foo();

위 코드에서 Foo 함수가 new 키워드와 함께 생성자 함수로 사용되는 즉시, 함수 내부의 this는 빈 객체가 되며 this.age = 50; 이라는 코드를 통해 그 빈 객체에 age라는 속성을 추가하고 50이라는 값을 할당하게 된다. 그러므로 두 번째 this.age에서는 50을 출력한다. 그리고 Foo 함수는 { age: 50 }이라는 객체를 리턴한다.

 

function Person() {

    this.name = 'henry';
    
    console.log(this);
    
}

var henry = new Person();

console.log(henry);

위 코드를 보면, Person이라는 함수가 있고, this.name = 'henry';라는 구문이 있다. 만약 위 코드가 일반 함수 실행 방식으로 실행되었다면 this는 window를 가리키게 되고 window 객체에 name이란 속성과 'henry'란 값이 추가되었을 것이다. 그리고 위 코드에는 return문이 없기 때문에 어떠한 값도 리턴하지 않으므로 henry란 변수에 어떤 것도 할당되지 않아 console창에는 undefined가 출력될 것이다. 

 

그러나 위 함수는 new Person(); 즉, 생성자 함수로 실행되었다. 따라서 this는 빈 객체를 생성하여 name이란 속성과 'henry'란 값을 할당할 것이고 return문이 없음에도 불구하고 그 객체가 리턴된다. 결국 henry란 변수에는 { name: "henry" }라는 객체가 할당되어 console.log에는 그 객체가 return된다.

 

function foo() {

    this.age = 50;
    
    return 10;
    
}

var a = new foo();

console.log(a);

생성자 함수는 return문이 있음에도 불구하고 그 return문을 무시하고 this 객체를 return하는 특징이 있다. 즉, 위의 코드에서 상식적으로 10이 return될 것 같지만, 생성자 함수로 사용되었기 때문에 { age: 50 }이 return된다.

 

function foo() {

    this.age = 50;
    
    return { height: 170 };
    
}

var a = new foo();

console.log(a);

하지만 생성자 함수도 return되는 대상이 객체라면 this 객체 대신에 해당 객체가 return된다. 즉, 위에서 a는 { age: 50 }이 아닌 { height: 170 }이 된다.

'JavaScript' 카테고리의 다른 글

DOMContentLoaded, Load, Unload (작성 중)  (0) 2022.01.11
동기식 vs. 비동기식 (작성 중)  (0) 2022.01.10
DOM과 BOM  (0) 2022.01.10
addEventListener 사용법  (0) 2022.01.10
콜 스택(call stack)  (0) 2022.01.08
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함