옹재
소소한 개발 블로그
옹재
전체 방문자
오늘
어제
  • 분류 전체보기 (66)
    • 개발 관련 서적 스터디 (6)
    • 프론트엔드 스터디 (36)
      • Javascript (16)
      • Typescript (13)
    • Vue 스터디 (22)
    • 개발 관련 스터디 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 프레임워크 없는 프론트엔드 개발
  • 프론트엔드 스터디
  • CSS
  • scss
  • 개발서적 스터디

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
옹재

소소한 개발 블로그

프론트엔드 스터디/Javascript

Javascript에서 this란?

2021. 7. 9. 15:15
728x90
반응형

Javascript에서 this란?

자바스크립트를 사용하면서 this에 대해 많이 헷갈렸습니다. 어떨 때는 this가 되고 어떤 함수에서는 this가 안되고 this가 어느 상황에서 어떤 것을 가르키는 것에 대해 잘 이해를 못하고 사용했습니다. 특히 저는 java를 많이 사용했었던 개발자로서 class 내의 this처럼 사용하려고 했습니다. this는 javascript에서 자주 사용되기도 하고 중요한 문법이기에 다시 한번 리마인드하면서 정리를 해보려고 합니다.

this란?

this는 '자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수'다. this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메소드를 참조할 수 있다.


보통의 this 정의를 찾아보면 위와 같습니다. 정의를 살펴보면 중간에 또는이라는 표현이 사용된 것을 볼 수 있습니다. 이는 this가 고정된 값에 바인딩되지 않기 때문입니다. this는 '함수가 호출되는 방식'에 따라서 동적으로 결정됩니다.

this 바인딩

this 바인딩을 통해 this가 어떤 값과 연결되는지 확인할 수 있습니다. 바인딩이랑 this의 호출 방식에 따라 this가 특정 '객체'에 연결되는 것입니다.

1. 전역 문맥에서는 모드 여부에 관계 없이 전역 객체 참조

console.log(this === window); //true

a = 30;
console.log(window.a); // 30

finction x() {
    return this;
}

x() === window; //true

'use strict' 
var x = this;
console.log(x === window); //true

전역 문맥에서 쓰이는 this는 엄격 모드 여부와 관계 없이 전역 window 객체를 참조합니다.

2. 함수 내부의 this는 함수 호출 방법에 따라 다르다.

단순호출

엄격모드가 아닌 함수 안에서 this는 함수의 주인에게 바인딩됩니다.

function f1() {
  return this;
}

// 브라우저
f1() === window; // true

// Node.js
f1() === global; // true

반면에 엄격 모드에서 함수 내의 this에 디폴트 바인딩이 없기 때문에 undefined가 됩니다.


"use strict";

function myFunction() {
  return this;
}
console.log(myFunction()); //undefined


"use strict";

var num = 0;
function addNum() {
  this.num = 100; //ERROR! Cannot set property 'num' of undefined
  num++;
}

addNum();

3. 메서드 안에서 쓴 this

일반 함수가 아닌 메서드에서는 this가 해당 메서드를 호출한 객체로 바인딩됩니다.

var person = {
  firstName: 'John',
  lastName: 'Doe',
  fullName: function () {
    return this.firstName + ' ' + this.lastName;
  },
};

person.fullName(); //"John Doe"


var num = 0;

function showNum() {
  console.log(this.num);
}

showNum(); //0

var obj = {
  num: 200,
  func: showNum,
};

obj.func(); //200

메서드 안의 함수 내부에서 this를 사용하면 전역 객체에 접근합니다.

var text = 'global';
var binding = {
  text: 'local',
  printText: function () {
    console.log(this.text); // local
    var innerFunc = function () {
      console.log(this.text); // global
    };
    innerFunc();
  }
};
binding.printText();

4. 이벤트 핸들러 안에서 쓴 this

이벤트 핸들러에서 this는 이벤트를 받는 HTML 요소를 가리킵니다.

var btn = document.querySelector('#btn')
btn.addEventListener('click', function () {
  console.log(this); //#btn
});

5. 생성자 안에서 쓴 this

생성자 함수가 생성하는 객체로 this가 바인딩 됩니다.

function Person(name) {
  this.name = name;
}

var kim = new Person('kim');
var lee = new Person('lee');

console.log(kim.name); //kim
console.log(lee.name); //lee

하지만 new 키워드를 빼먹는 순간 일반 함수 호출과 같아지기 때문에, 이 경우는 this가 window에 바인딩됩니다.

var name = 'window';
function Person(name) {
  this.name = name;
}

var kim = Person('kim');

console.log(window.name); //kim

6. 명시적 바인딩

명시적 바인딩은 함수의 call, apply, bind 메소드를 사용해서 함수 내부에서 사용되는 this의 값이 어떤 값이 사용되야하는지 명확할 때 사용하는 방식입니다.

var name = "chris";
var age = 100;
function person(){
    console.log("이름 : ", this.name);
    console.log("나이 : ", this.age);
}

var mark = {
    name : "mark",
    age : 15
}

var tomas = {
    name: "tomas",
    age: 17
}

// 전역객체 this를 바인딩
person();

//call과 apply를 사용하여 person 내부에서 사용된 this의 값을 명시적으로 설정합니다. 
person.call(mark);
person.apply(tomas);

//bind의 경우 함수를 직접 호출하지 않고 this가 명시적으로 설정된 함수를 반환합니다. 실행을 위해서는 반환받은 함수를 직접 실행해야합니다. 
var tmp = person.bind(mark)
tmp();
//call vs apply
var age = 100;

function person(a,b,c,d,e){
    console.log('age : ', this.age);
    console.log('arguments : ', arguments);
}

var ken = {
    age: 43
}

//call 함수의 경우 인자를 ,를 사용하여 여러개 받을 수 있습니다.
person.call(ken, 1,2,3,4);
person.call(ken, 1,2,3,4,5);
person.call(ken, 1,2,3,4,5,6);

//apply 함수의 경우 인자를 array 객체 하나만 받습니다.
person.apply(ken, [1,2,3,4]);
person.apply(ken, [1,2,3,4,5]);
person.apply(ken, [1,2,3,4,5,6]);

7. new를 통한 바인딩

function Foo() {
    console.log(this);
}

new Foo(); // Foo

new를 통해 생성하게되면 this는 새로 생성된 객체를 가르킵니다.

8. 화살표 함수로 쓴 this

화살표 함수에서 this는 자신을 감싼 정적 범위입니다. 화살표 함수는 전역 컨텍스트에서 실행되더라도 this를 새로 정의하지 않고, 바로 바깥 함수나 클래스의 this를 사용합니다.

var Person = function (name, age) {
  this.name = name;
  this.age = age;
  this.say = function () {
    console.log(this); // Person {name: "Nana", age: 28}

    setTimeout(function () {
      console.log(this); // Window
      console.log(this.name + ' is ' + this.age + ' years old');
    }, 100);
  };
};
var me = new Person('Nana', 28);

me.say(); //global is undefined years old

위 코드를 보면 내부 함수에서 this가 전역 객체를 가리키는 바람에 의도와는 다른 결과가 나왔습니다.

var Person = function (name, age) {
  this.name = name;
  this.age = age;
  this.say = function () {
    console.log(this); // Person {name: "Nana", age: 28}

    setTimeout(() => {
      console.log(this); // Person {name: "Nana", age: 28}
      console.log(this.name + ' is ' + this.age + ' years old'); 
    }, 100);
  };
};
var me = new Person('Nana', 28); //Nana is 28 years old

화살표 함수로 바꾸면 setTimeout을 감싼 함수의 this를 사용하기 때문에 person 객체를 가르키게 됩니다.

728x90
반응형

'프론트엔드 스터디 > Javascript' 카테고리의 다른 글

자바스크립트 실행 컨텍스트  (0) 2021.07.12
자바스크립트에서 scope란?  (0) 2021.07.12
Prototype이란?  (0) 2021.07.12
자바스크립트에서 함수란?  (0) 2021.07.09
strict mode(엄격모드)란?  (0) 2021.07.09
    '프론트엔드 스터디/Javascript' 카테고리의 다른 글
    • 자바스크립트에서 scope란?
    • Prototype이란?
    • 자바스크립트에서 함수란?
    • strict mode(엄격모드)란?
    옹재
    옹재

    티스토리툴바