본문 바로가기
개발 지식 A+/FE

this 키워드

by ddubbu 2021. 1. 26.
728x90
반응형

이 문서는 MDN과 코드스테이츠 학습 자료를 토대로 정리하였습니다. this는 함수 실행 시 호출 방법에 의해 결정되는 객체이다. 즉, execution context에 따라 결정된다. 아래와 같이 크게 5가지의 경우로 나누고, strict mode 유무, 화살표 함수는 나중에 다루도록 하겠다.

 

Execution Context 

  1. Global 참조
  2. Function 호출
  3. Method 호출
  4. new 키워드를 이용한 생성자 호출
  5. .call 또는 .apply 호출

세부적으로 살펴보도록 하자.

Execution Context this에 바인딩되는 객체  
Method 부모 객체 (실행 시점에 온점 왼쪽에 있는 객체) obj = { var fn : function( ){ return this} } 
test1 = obj.fn() // = obj
test2 = obj.fn // = window
Class new 키워드를 이용해 새롭게 생성된 인스턴스 객체  객체 지향 프로그래밍
.call(B)
.apply(B)
첫번째 인자로 전달된 객체 (생략시 B = 아래 함수 Execution Context 유형 따름) B로 Context 이동 
Using call to invoke a function and specifying the context for 'this'
If the first argument is not passed, the value of this is bound to the global object (in strict mode, the value of this will be undefined)

아래 2가지 경우는 권장하지 않는다. 런타임 환경 및 strict mode 유무에 따라 바인딩되는 객체가 다르기 때문이다.

  브라우저 node.js
Global window (undefined in strict mode) module.exports
Function window (undefined in strict mode) global
  • strict mode 란?
    가벼운 Error를 무시하지 않고, Throwing 하는 모드이다. 원하는 Context에 'use strict' 를 사용하면 된다. 

call vs apply vs bind

call apply bind
this 값 및 전달된 인수와 함께 함수를 실행한다. this 바인딩된 함수를 리턴.
argument list single array (array-like object) of arguments  
    in the new function it is pemanently bound to the first argument of bind
  • apply 심화

Spread Syntax 대신 사용해도 되겠고만,

arr = [1, 2, 3, 4]

/*1. this 생략*/
Math.max(...arr) // 4
Math.max.apply(null, arr) // 4

/*2. this 넘겨주기*/
arr.push([5]) // arr = [1, 2, 3, 4, [5]]
arr.push(...[5]) // arr = [1, 2, 3, 4, 5]
arr.push.apply(arr, [5]) // [1, 2, 3, 4, 5]
  • Class
function Food(name, price) {
  this.category = 'food'
}

let cheese = new Food('feta', 5000) // cheess는 Food이면서 Product입니다.

 

bind method

  1. 이벤트 핸들러
// 1. wihtout binding
btn.onclick = handler

function handler(){
	console.log(this.toString()) 
}

/* btn 클릭 후 console 창 결과
<button> ... </button>
*/

// 2. with binding
btn.onclick = hanlder.bind(btn.textContent);
/* btn 클릭 후 console 창 결과
//버튼 내용 출력됨
*/

 

2. setTimeout

callback 함수에 자동으로 window 함수를 binding 한다는 특징이 있다. 조심하자.

class Factory{
  constructor(x){
    this.x = x
  }

  printX(){
    console.log("result:", this.x);
  }

  printAsync1(){ // undefined
  // setTimeout은 callback 함수에 window를 binding 한다.
    setTimeout(this.printX, 2000); 
  }

  printAsync2(){
    setTimeout(this.printX.bind(this), 2000);
  }

  printAsync3(){ // 권장하지 않음.
    let self = this;
    setTimeout(function(){
      self.printX()
    }, 2000)
  }

  printAsync4(){
    setTimeout(()=>{
      this.printX(); // 화살표 함수는 실행되는 곳에서 binding 된다?
    }, 2000)
  }

}

let x = new Factory("this is x");

x.printAsync1(); // 번호 바꿔가면서

 

getter, setter

obj 내부에 멤버 변수끼리 참조하려면, get keyword와 this keyword를 사용해야해.

 

const obj = {
  arr : [1, 2, 3, 4],
  get fn(){
    return this.arr.length
  }
}

console.log(obj.fn); // 4

혹은

const obj = Object.create(null) //const obj = {}
Object.defineProperty(o, 'b', { get: function() { return this.a + 1; } });

Arrow Function

1. function keyword

var obj = { bar: function(){ return this } };

let Exe = obj.bar();
console.log(Exe); // obj

let noExe = obj.bar;
console.log(noExe()); // window

poiemaweb.com/es6-arrow-function 여기서 살펴보면,

function Maker(x) {
  this.x = x;
}

Maker.prototype.Check = function (arr) {
  console.log("(A)", this);
  return function Check(arr){
        console.log("(B)", this);
    };
};
var instance = new Maker("this");
instance.Check()();

/* console 결과
(A) Maker {x: "this"}
(B) Window ...

*/

var noExe = instance.Check(); //(A) Maker {x: "this"}
noExe(); // (B) Window

var noNoExe = instance.Check;
noNoExe() // (A) Window
noNoExe()() // (A) Window \n (B) Window

 

 

2. Arrow Function

var obj = { bar: function(){ return this } };

let Exe = obj.bar();
console.log(Exe); // obj

let noExe = obj.bar;
console.log(noExe()); // window

 

var obj = { bar: ()=>this };

let Exe = obj.bar();
console.log(Exe); // window

let noExe = obj.bar;
console.log(noExe()); // window

method 형태로 실행되면,

arrow function은 어디서 실행되든, window

그 외 function은 실행 위치에서 binding 된다고 이해했는데 왠걸?

 

잠깐만, 화살표 함수에서 this는 싸여진 렉시컬 컨텍스트의 것으로 유지됩니다.

var obj = {
  bar: function() {
    var x = (() => this);
    return x;
  }
};

let Exe = obj.bar();
console.log(Exe()); // === obj

let noExe = obj.bar;
console.log(noExe()()); // === window

 

 

 

 

it('화살표 함수 호출시 this값을 확인합니다', () => {

const foo = () => {

return this

}

expect(foo()).to.eql(global) // 여기서 global이 아니라, {} 라니?

})

 

 

# GUI git

smartgit

sourcetree

 

# 과제 제출

git push 이후 > npm run submit

npx codestates-submission ls

 

# VS Code - debugger

반응형

'개발 지식 A+ > FE' 카테고리의 다른 글

Redux  (0) 2021.01.26
Hooks 공식문서로 이해하기  (0) 2021.01.26
how to show cookie headers at client  (0) 2021.01.20
[반응형 웹] #1. 미디어 쿼리  (0) 2021.01.09
webpack 환경 설정  (0) 2021.01.09