공부혜옹

[JavaScript vs Java] This 본문

공부합시다/JavaScript

[JavaScript vs Java] This

Blair06 2020. 5. 24. 22:02

나는 Java를 먼저 배워서 JS에서의 this또한 당연히 Java와 같겠거니 생각했었다. 때문에 이부분의 개념은 넘어가도 되겠거니 했으나...크나큰 착각이었다.

Java에서의 this

Java에서의 this는 객체 자신(self)을 가리키는 참조변수로, this가 객체 자신에 대한 참조 값을 가지고 있다는 뜻이다.
주로 매개변수와 객체 자신이 가지고 있는 멤버변수명이 같을 경우 이를 구분하기 위해서 사용된다. 

public Class Car {
  private String name; // a
  
  public Person(String name) { //b
    this.name = name; //this.a = b;
  }
}

 

JavaScript에서의 this

자바스크립트의 경우 함수 호출 방식에 의해 this에 바인딩할 어떤 객체가 동적으로 결정된다. 

함수호출

  • 내부함수는 일반함수, 메소드, 콜백함수 어디에서 선언되었는지에 관계없이 this는 전역객체를 바인딩한다.
  • 전역객체는 모든 객체의 최상위 객체를 의미하며 일반적으로 Browser-side에서는 window, Server-side(Node.js)에서는 global 객체를 의미한다.하지만 아래 코드의 this는 window혹은 global객체가 아닌 obj를 가리킨다. 객체의 메서드를 호출할 때 this를 내부적으로 바꿔주기 때문이다.
var obj = {
  a: function() { console.log(this); },
};
obj.a(); // obj

호출하는 함수가 객체의 메소드인지 그냥 함수인지가 중요하다. 아래의 a2는 obj.a를 꺼내온 것이기 때문에 더 이상 obj의 메소드가 아니다.

var a2 = obj.a;
a2(); // window

또한 메소드의 내부함수일 경우에도 this는 전역객체에 바인딩된다.

var value = 1;

var obj = {
  value: 100,
  test: function() {
    console.log("foo's this: ",  this);  // obj
    console.log("foo's this.value: ",  this.value); // 100
    function bar() {
      console.log("bar's this: ",  this); // window
      console.log("bar's this.value: ", this.value); // 1
    }
    bar();
  }
};

obj.test();

 

call, apply, bind 메소드
이렇듯 함수 호출에 따라 바뀌는 this를 피하기 위해 아예 명시적으로 this를 지정해주는 메소드가 존재한다.

call과 apply는 this 객체를 지정하며 함수를 호출하는 메소드이다.
첫 번째 인자에 this로 지정하고 싶은 객체를 넘겨주어 this를 바꾸고나서 해당 함수를 실행한다

const obj = {name: `hyewon`};

const introduce = function(age){
	console.log(`My name is ${this.name}. I'm ${age} years old.`);
}

introduce(23); // My name is undefined. I'm 23 years old.
introduce.call(obj, 23); //My name is hyewon. I'm 23 years old.
introduce.apply(obj, [23]); // My name is hyewon. I'm 23 years old.

introduce(23);의 경우 this는 window객체이다.window전역변수 name이 존재하지 않기 때문에 undefined로 출력된다.
call과 apply메소드를 사용하여 함수를 호출한 경우 this가 지정하는 객체가 obj로 바뀌었다. (this.name === obj.name)
call과 apply의 차이점은 파라미터를 입력하는 방식이다. apply메소드는 call과 달리 두번째 인자부터 배열에 넣는다.

bind메소드는 call, apply와 달리 함수를 실행하지 않는다. 다만,obj를 this로 지정한 bound함수를 리턴한다.

const obj = {name: `hyewon`};

const introduce = function(age){
	console.log(`My name is ${this.name}. I'm ${age} years old.`);
}

const bound = introduce.bind(obj);
bound(23); //My name is hyewon. I'm 23 years old.

 

생성자 함수 호출

JavaScript의 생성자 함수는 JAVA와 같은 객체지향 언어의 생성자함수와 다르게 그 형식이 정해져있는것이 아닌, 기존함수에 new연산자를 붙여서 호출하면 해당 함수가 생성자함수로 동작한다. 이렇게 new를 붙이면 생성자를 통해 생성된 인스턴스가 this로 지정된다. 

반응형
Comments