자바스크립트에서 함수가 호출될 때 매개변수로 전달되는 인자외에 arguments객체this를 자동으로 전달받게 된다.

2021/01/28 - [개발/Javascript] - arguments, rest parameter

 

arguments, rest parameter

arguments arguments는 함수가 호출될 때 전달받은 모든 인수를 참조할 수 있는 'Array형태' 객체로, 모든 함수 내에서 이용 가능한 지역 변수이다. *Array 형태 : 배열(Array)의 length 속성과 더불어 0부터

jwookj.tistory.com

javascript에서 this는 함수가 소속된 객체를 가리키는데 Java와는 달리 this에 바인딩되는 객체는 해당 함수 호출 방식에 따라  달라진다.

 

*바인딩(Binding)이란 함수 호출과 실제 함수를 연결하는 방법이다. 즉 함수를 호출하는 부분에 함수가 위치한 메모리 번지를 연결시켜 주는 것이다.

 

함수의 호출 방식

  1. 함수 호출

  2. 메서드 호출

  3. 생성자 함수 호출

  4. apply, call 호출

 

함수 호출

원시 타입을 제외한 자바스크립트의 모든 값들은 객체이다. 그중 최상위에 위치한 객체를 전역 객체(global object)라고 한다.

브라우저에서의 전역 객체 : window

node.js(서버)에서의 전역 객체 : global

 

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

function func() {
  if(this === global){
      console.log("func this = global");
  }
  function innerFunc() { //내부함수
    if(this === global){
      console.log("innerFunc this = global");
    }
  }
  innerFunc();
}
func()
//func this = global
//innerFunc this = global

 

함수 호출 참고

  • global scope에서 선언한 전역 변수와 함수는 전역 객체의 property와 method가 된다.

  • 기본적으로 this는 전역 객체에 바인딩된다.

  • 내부 함수의 this는 일반 함수, 메서드, 콜백 함수 어디에서 선언되었는지에 관계없이 전역 객체에 바인딩된다.

메서드 호출

함수가 객체의 메서드라면 this는 해당 메서드를 호출한 객체에 바인딩된다.

 

//전역객체에서 메소드 호출
function func() {
  if(this === global){
      console.log("func this = global");
  }
}

global.func()
//func this = global


//funcObj객체에서 메소드 호출
let funcObj = {
  "func" : function () {
  if(this === global){
      console.log("func this = global");
    }
    else if (this === funcObj) {
      console.log("func this = funcObj")
    }
    else{
      console.log("don`t know`")
    }
  }
}

funcObj.func();
//func this = funcObj


//funcObj객체에서 메소드 호출을 실행하였으나 내부함수(innerFunc)의 this는 전역객체 global에 바인딩된다.
let funcObj = {
  "func" : function () {
  if(this === global){
      console.log("func this = global");
    }
    else if (this === funcObj) {
      console.log("func this = funcObj")
    }
    else{
      console.log("don`t know`")
    }
    function innerFunc() { //내부함수
      if(this === global){
        console.log("innerFunc this = global");
      }
      else if (this === funcObj) {
        console.log("innerFunc this = funcObj")
      }
      else{
        console.log("don`t know`")
      }
    }
    innerFunc();
  }
}

funcObj.func();
//func this = funcObj
//innerFunc this = global

메서드 호출에서도 내부 함수는 전역 객체에 바인딩된다.

 

생성자 함수 호출

생성자 함수 호출 시 작동 순서

  1. 빈 객체 생성 및 this가 빈 객체에 바인딩된다.
  2. this를 통한 property와 method 생성
  3. 생성된 객체 반환
function FuncObj(name) {
//this를 통한 맴버 생성
  this.name = name;
  this.func = function() {
    console.log(`func this = ${this.name}`);
  }
//생성된 함수 반환
}

let func1 = new FuncObj("func1");
let func2 = new FuncObj("func2");

console.log(func1.name)
func1.func()
console.log(func2.name)
func2.func()
//func1
//func this = func1
//func2
//func this = func2

생성자 함수 호출 참고

  • new 키워드를 통해 생성자 함수를 호출하게 되면 this는 생성된 객체를 가리키게 된다.

  • 일반 함수와 생성자 함수에 특별한 차이는 없으며, 함수에 new 연산사를 붙여 호출하면 해당 함수는 생성자 함수로 동작한다.

  • 일반 함수를 호출하면 this는 전역 객체에 바인딩되지만, new 연산자와 함께 생성자 함수를 호출하면 생성자 함수 내부의 this는 생성자 함수에 의해  암묵적으로 생성된 빈 객체를 가리킨다. 

생성자 함수에 new 연산자를 붙이지 않고 호출할 경우, 함수 내부의 this는 전역 객체에 바인딩된다.
또한 new와 함께 생성자 함수를 호출하는 경우에 암묵적으로 반환하던 this도 반환하지 않으며, 반환문이 없으므로 undefined를 반환하게 된다.

 

이러한 위험을 회피하기 위해 사용되는 Scope-Safe Constructor 패턴

// Scope-Safe Constructor Pattern
function A(arg) {
  // 생성자 함수가 new 연산자와 함께 호출되면 함수의 선두에서 빈객체를 생성하고 this에 바인딩한다.

  /*
  this가 호출된 함수(arguments.callee, 본 예제의 경우 A)의 인스턴스가 아니면 new 연산자를 사용하지 않은 것이므로 이 경우 new와 함께 생성자 함수를 호출하여 인스턴스를 반환한다.
  arguments.callee는 호출된 함수의 이름을 나타낸다. 이 예제의 경우 A로 표기하여도 문제없이 동작하지만 특정함수의 이름과 의존성을 없애기 위해서 arguments.callee를 사용하는 것이 좋다.
  */
  if (!(this instanceof arguments.callee)) {
    return new arguments.callee(arg);
  }

  // 프로퍼티 생성과 값의 할당
  this.value = arg ? arg : 0;
}

var a = new A(100);
var b = A(10);

console.log(a.value);
console.log(b.value);
//100
//10

 

apply, call 호출

함수 호출 패턴에 의해 결정되는 암묵적 this 바인딩 이외에 this를 특정 객체에 명시적으로 바인딩하는 방법

//생성자 함수 FuncObj
function FuncObj(name) {
  this.name = name;
  this.func = function(){
    console.log(`func this = ${this.name}`);
  }
}
let func1 = {};

//두가지 방법 모두 같은 결과를 출력
FuncObj.apply(func1, ["JJJ"]);
FuncObj.call(func1, "JJJ");

console.log(func1);
func1.func()
//{ name: 'JJJ', func: [Function] }
//func this = JJJ

apply, call 참고

  • apply와 call 모두 함수 객체에 속해있는 method이다.

  • this를 특정 객체에 바인딩해준다.

  • 본질적인 기능은 함수 호출이다.

 

참고

poiemaweb.com/js-this

 

this | PoiemaWeb

자바스크립트의 this keyword는 Java와 같은 익숙한 언어의 개념과 달라 개발자에게 혼란을 준다. Java에서의 this는 인스턴스 자신(self)을 가리키는 참조변수이다. this가 객체 자신에 대한 참조 값을

poiemaweb.com

opentutorials.org/course/743/6571

 

this - 생활코딩

this는 함수 내에서 함수 호출 맥락(context)를 의미한다. 맥락이라는 것은 상황에 따라서 달라진다는 의미인데 즉 함수를 어떻게 호출하느냐에 따라서 this가 가리키는 대상이 달라진다는 뜻이다.

opentutorials.org

velog.io/@litien/Javascript-This-Binding

 

[Javascript] This Binding

어제 만난 웨일 확장앱을 개발하면서 만난 이슈는 다음과 같다. Class 내부의 콜백함수에서 클래스 내부 메소드를 호출하는데 this가 바인딩되지 않아 함수 호출이 이루어지지 않았다. fetch API를

velog.io

 

'개발 > Javascript' 카테고리의 다른 글

데이터 타입, 표준 내장 객체(Standard Built-in Object), 타입 변환  (0) 2021.02.03
prototype(프로토타입)  (0) 2021.02.02
객체(object)  (0) 2021.01.28
arguments, rest parameter  (0) 2021.01.28
closure(클로저)  (0) 2021.01.27

+ Recent posts