this 키워드는 자바스크립트와 다른 클래스 기반 언어와는 약간 다른개념이다.
C++에서 this라함은 보통 이를 사용하는 멤버함수가 속한 클래스를 가르키는 포인터이고, java또한 비슷한 기능을 가진다.
이렇게 클래스 기반언어 C++/JAVA의 this는 기능이 정해져있다.

자바스크립트 또한 클래스기반 언어 처럼 같은 기능을 제공하지만, this 키워드를 사용하는 방법에 따라 가르키는 대상이 모두 다르다.


자바에서의 this

class Memeber{
    private String id;
    private String password;
    
    Memeber{String id, String password){
        this.id = id;
        this.password = password;
    }
}

C++에서의 this

class Brick{
private:
    int shape;
    int rot;
public:
    Brick(){
    srand(GetTickCount());
    this->shape = rand() % 6; 
    this->rot = rand() % 3; 
    }
};  

 

'This'

자바스크립트에서 this가 가르키는 경우는 크게 5가지의 경우로 나타낼 수 있다.

1. Global Scope에서 사용될 때 this는 전역 객체를 가르킨다(window 객체)

2. 함수에서 사용될 때에도 this는 전역 객체를 가르킨다.(window 객체)

3. 객체에 속한 메서드에서 사용될 때 this는 메서드가 속한 객체를 가르킨다.

4. 객체에 속한 메서드의 내부함수에서 사용될 때 this는 전역 객체를 가르킨다.(window 객체)

5. 생성자에서 사용될 때, this는 이 생성자로 인해 생성된 새로운 객체를 가르킨다.


이렇게 정리해놓고 보니, 4번의 경우를 제외하고 this도 일반적으로 자기가 속한 객체를 가르키는것으로 알 수 있다.


1. Global Scope에서 사용될 때 this는 전역 객체를 가르킨다(window 객체)

var func = {}; //객체 생성

this === window;//true

this === func;//false

다음과 같이 global scope에서 this와 전역객체를 비교해보면 true를 반환한다. global scope 자체가 전역객체(window)이므로  전역변수들과 함수들은 모두 전역객체에 속한다.


2. 함수에서 사용될 때에도 this는 전역 객체를 가르킨다.(window 객체)

function func(){
    if(this===window)
        console.log("this===window");
}

func();

1번과 같은 맥락으로 global scope가 전역객체이므로 함수는 전역객체에 속하는 메서드와 같다. this는 자신이 속한 메서드를 가르키므로 함수의 this는 window를 가르킨다. 따라서 이 코드의 함수 내 if문은 올바르게 작동하여 "this===window"를 출력한다.


3. 객체에 속한 메서드에서 사용될 때 this는 메서드를 호출한 객체를 가르킨다.

var obj = { func : function(){ if(this===window){ console.log("this===window"); } else if(this===obj){ console.log("this===obj"); } } } object.func();

메서드를 하나 가지고있는 객체를 생성했다. 이 객체의 메서드 func는, this가 window일때와 obj일때에 따라 다른 결과를 출력한다.

코드를 실행해보면 this===obj가 출력된다. 따라서 객체에 메서드가 사용하는 this는 자신이 속한 객체를 가리킴을 알 수 있다.


4. 객체에 속한 메서드의 내부함수에서 사용될 때 this는 전역 객체를 가르킨다.(window 객체)

var obj = { func : function(){ function inner(){ if(this===window){ console.log("this===window"); } else if(this===obj){ console.log("this===obj"); } } inner(); } } obj.func();

 

3번의 코드에서 메서드에 내부함수를 추가하고 그 안에 this가 어떤 객체에 속하는지 확인하는 코드를 넣었다. 이코드의 결과로는 놀랍게도 "this===window"가 출력된다. 따라서 내부함수에서 this를 사용할때에는 주의를 요한다.
내부함수에서 자신이 속한 객체를 가르키는 this 키워드가 필요할 시 보통은 다음과 같이 메서드 내에서 this를 변수에 따로 저장하여 그 변수를 사용하는 방법을 취한다.


var obj = { func : function(){ var that = this; function inner(){ if(that===window){ console.log("that===window"); } else if(that===obj){ console.log("that===obj"); } } inner(); } } obj.func();

위 코드는 "that===obj"가 출력된다.위 방법 외에 아래와 같이 bind 메서드를 사용해서 같은 결과를 출력할 수 있다. 밑의 코드는 "this===obj"를 출력한다

var obj = {
    func : function(){
        var inner = function(){
            if(this===window){
                console.log("this===window");
            }
            else if(this===obj){
                console.log("this===obj");
            }
        }.bind(this);
        inner();
    }
}

obj.func()

 

5. 생성자에서 사용될 때, this는 이 생성자로 인해 생성된 새로운 객체를 가르킨다.

function obj(){ this.thisValue = this; this.func = function(){ if(this===window){ console.log("this===window"); } else if(this===obj){ console.log("this===obj"); } else{ console.log("this===other Object"); } } } var A = new obj(); A.func();

이는 일반적인 this 사용과 같다. 위 생성자의 프로퍼티로 들어있는 func메서드는 this가 어떤 값인지를 출력한다. 새로운 객체를 생성하고 위 메서드를 실행해보면,"this===other Object"가 출력된다. 즉 여기서 this는 window도, obj아닌 새로운 값을 가진다는 것을 알 수 있다.
이 this는 새롭게 생성된 객체 A를 가르키는지 확인을 위해 다음 코드를 입력해보자.

A.thisValue === A

여기서 thisValue 프로퍼티는 this의 값을 저장하고 있다. 위 코드를 입력하면 true를 반환하는데, 이를 통해 생성자의 this는 새로운 객체를 생성할 시 그 객체(여기서는 객체 A)를 가르킴을 확인할 수 있다.

 

apply 메서드와 call 메서드로 this 제어

this는 이렇게 어디서 사용되냐에 따라 참조하는 값이 다르다. 근데 function.prototype의 apply 메서드와 call 메서드를 이용해서 이 this 키워드를 제어할수 있다. 즉 위에 정해진 5가지 경우와 다르게 다른 값을 참조하도록 만들어줄 수 있다.

apply와 call은 인자값만 조금 다르고, 결과는 모두 같으므로 apply로만 예제를 보도록 하겠다.

var obj = {};
function func(){
    if(this===window)   
        console.log("this===window");
    else if(this===obj)
        console.log("this===obj");
    }
    
func();
func.apply(obj);

기본적으로 함수 func는 grobal scope에 존재하므로 this는 전역객체(window)를 가르킨다. 따라서 func를 실행하면 "this===window"가 출력된다.

하지만 apply로 인자값에 obj를 전달하여 func.apply(obj)를 실행하면 "this===obj"가 출력된다. 즉 apply를 통해 저 함수의 this값을 obj로 변경하여 함수가 실행되었다.

apply는 인자로 바인딩할 객체와, 해당 함수에 전달할 인자들을 '배열'로 입력받는다. 반면 call은 배열이 아닌 인자들도 입력받는다는 점이 다르니 이는 입맛이나 때에 따라 사용하자.

ex) func.apply(obj,[a,b,c]);    func.apply(obj,a,b,c);



접근제어자 public으로써의 this 

자바스크립트에서는 C++과 JAVA와 같이 public이나 private같은 접근제어자가 따로 존재하지 않는다. 하지만 var,this로 객체를 캡슐화 할 수 있다.

function Member(id,password){
    this.id = id;
    var pass = password;
    this.getPassword = function(){
        return pass;
    }
}

var newUser = new Member("hsp1116","12345");

console.log(newUser.id);
console.log(newUser.pass);
console.log(newUser.getPassword());

위 코드를 실행해보면 console.log(newUser.id)는 올바르게 id를 출력하지만 console.log(newUser.pass)는 undefiend가 출력된다. this.id는 노출되지만 var.pass는 은닉화 된것이다.
대신 getter메서드인 console.log(newUser.getPassword())는 올바르게 출력되는것을 확인할 수 있다.

 

+ Recent posts