[javascript] this bind, this 바인딩(어렵다 어려워)

728x90
반응형

 

미리보기 로고 그려봤어요 ㅋㅋㅋㅋ 

 

* boycoding.tistory.com/22?category=915176

jeonghwan-kim.github.io/2017/10/22/js-context-binding.html

 

글을 읽고 공부하며 요약정리한 글입니다

 

this는 함수가 호출되는 패턴에 따라서 다른 객체를 참조(바인딩) 한다

 

  1. 객체 메서드 호출: 메서드를 호출하는 객체에 바인딩
  2. 함수를 호출: 전역 객체에 바인딩 (내부 함수 호출 포함)
  3. 생성자 함수 호출: 새로 생성되는 객체에 바인딩

 

1. 객체 메서드 호출 

const a={
  name:'sara',
  output:function(){
    console.log(this.name);
  }
}

const b={name:'b'}

b.output=a.output

a.output(); //sara 암시적 바인딩
b.output(); //b

1. 암시적 바인딩

  • 객체의 프로퍼티로 접근해서 실행하는 것을 암시적 바인딩이라고 한다
  • 위에서 a.ouput()은 a 객체의 output 프로퍼티에 함수를 할당(메소드)해서 name프로퍼티를 호출하고 있다
  • b의 output은 b 객체의 name 프로퍼티에 접근하여 호출하고 있다

 

✨ 실수하는 부분 (콜백 함수 호출)

function hello() {
  console.log(this.name)
}

var obj = {
  name: "chris",
  hello: hello,
}

setTimeout(obj.hello, 1000) // 1초 후에 hello 함수가 동작하면 this는?

name = "global context!"

// 출처: https://jeonghwan-kim.github.io/2017/10/22/js-context-binding.html

setTimeout의 obj.hello가르키는 hello()함수만 알고있다.

1초 후에 실행하는 코드는 전역 컨텍스트에 this를 바인딩 한다 (global context가 출력된다)

 

2. 명시적 바인딩 (콜백 함수 바인딩 해결 방법)

call(), apply(), bind() 함수의 사용

 

function hello() {
  console.log(this.name)
}

var obj = {
  name: "chris",
}

name = "global context!"
hello.call(obj) // "chris"

// 출처: https://jeonghwan-kim.github.io/2017/10/22/js-context-binding.html

hello 함수를 obj객체와 바인딩 시켰다

 

function hello() {
  console.log(this.name)
}

var obj = {
  name: "chris",
  hello:hello
}

setTimeout(obj.hello.bind(obj), 1000) // 1초 후에 hello 함수가 동작하면 this는?

name = "global context!"

//출처: https://jeonghwan-kim.github.io/2017/10/22/js-context-binding.html

원 출처의 obj.hello 부분이 없어서 추가했다

obj.hello를 넘겨주면 글로벌 컨텍스트가 바인딩 되는데, bind함수로 obj 객체로 this를 바인딩하게 된다.

bind()로 바인딩하는 것을 하드 바인딩이라고 한다

bind와 call,appy의 동작이 조금 다르다. call으로 명시적으로 바인딩 해줘도 콜백함수로 던져주면 글로벌 컨텍스트에 this가 바인딩 된다

 

3. New 바인딩

생성자 함수 바인딩 (클래스, 생성자 부분에서 공부)

function Person(name) {
  this.name = name
}
Person.prototype.hello() {
  console.log(this.name)
}

var obj = new Person('chris');
obj.hello(); // "chris"

new Person(name)을 호출하면 새로운 객체 (인스턴스)를 반환한다.

obj.hello()는 new로 반환된 obj 객체를 this 로 바인딩한다.

즉, 반환되는 값이 this!

 

함수 호출 바인딩

 

기본적으로 전역 객체에 컨텍스트가 바인딩 된다

브라우저에서 전역객체는 window 객체이다. (노드는 global)

let name='window name';
function hello(){
console.log(this.name);
}

hello(); //window name

내부 함수 호출 바인딩 (전역 객체에 this가 바인딩 된다)

 

우선순위 : new 바인딩 > 명시적 바인딩 > 암시적 바인딩

 

어휘적 this (화살표 함수)

기존의 바인딩은 실행 시점에 바인딩 되는 동적 바인딩이다.

화살표 함수는 실행하지 않고도 this를 알 수 있는 정적 바인딩이다.

코드 상 상위 블록의 컨텍스트를 this로 바인딩한다

 

// 기본 함수 바인딩 
function hello() {
  setTimeout(function callback() {
    console.log(this.name)
  })
}

var obj = {
  name: "chris",
  hello: hello,
}

var name = "global contenxt!"

hello() // 'global contenxt!'
obj.hello() // 'global contenxt!'
hello.call({ name: "chris" }) // 'global contenxt!'

// 화살표 함수 바인딩

function hello() {
  setTimeout(() => {
    console.log(this.name)
  })
}
var obj = {
  name: "chris",
  hello: hello,
}
var name = "global contenxt!"

hello() // 'global contenxt!'
obj.hello() // 'chris'
hello.call({ name: "alice" }) // 'alice'

// 출처: https://jeonghwan-kim.github.io/2017/10/22/js-context-binding.html

setTimeOut함수가 콜백 형태로 호출하면서 this는 글로벌 객체로 바인딩 된다

** 명시적 바인딩을 해줘도 bind가 아닌 call, apply의 경우에는 콜백함수가 실행되는 시점에 글로벌 컨텍스트로 바인드된다.

 

(* hello.call에서 멘붕왔다, 명시적으로 던져줘도 글로벌로 바인딩 되는게 아직도 이해가 안간다. 일단 bind()함수로 바인딩시키면 제대로 출력되는데 반환한 결과값이 this가 되어서 그런건가..? bind()는 되고 call()은 안되는게 이해가 안간다)

 

-- 추가 2020.12.14  --

this를 더 공부하다가 알았다 call, apply는 명시적으로 실행한 결과값을 반환하고 bind는 this를 묶은 함수를 리턴해준다.  bind로 반환한 함수가 호출될 때 this가 묶인 함수이므로 제대로 된 결과값을 반환한다. 

apply, call은 함수를 호출한 결과를 반환하고 기존 함수는 this가 다시 끊긴다

 

 

화살표 함수의 경우 상위 스코프(블록)의 this를 바인딩하므로 제대로 출력된다

 

기본 함수 호출 this 바인딩

 

함수 호출시 this는 전역 객체에 바인딩 된다

** 메서드의 내부 함수를 호출할 때도 전역에 바인딩된다

 

var value=100;

const test={
  value:1,
  outer:function(){
    this.value+=1;
    console.log('outer func',this.value);
    
    inner=function(){
      this.value+=1;
      console.log('inner func',this.value);
    }
    
    inner();
  }
}

test.outer();

// "outer func" 2
// "inner func" 101




//출처: https://boycoding.tistory.com/22?category=915176 [소년코딩]
// 코드 좀 변경해봤습니다

outer 함수의 경우 암시적 바인딩으로 내부 프로퍼티인 value값에 접근한다 

inner 함수의 경우 글로벌 객체에 this가 바인딩 된다 (호출시)

 

var that=this; 해서 내부 함수에서 that을 this 대신으로 사용하기도 하지만 옛날 방식이다.

 

다른 해결방법: 화살표 함수 

 

위에서 공부한 것처럼 화살표 함수를 통해서 해결해준다 (화살표 함수 만세!)

var value=100;

const test={
  value:1,
  outer:function(){
    this.value+=1;
    console.log('outer func',this.value);
    
    inner=()=>{
      this.value+=1;
      console.log('inner func',this.value);
    }
    
    inner();
  }
}

test.outer();

// "outer func" 2
// "inner func" 3

 

--

 

예전에 공부했지만 다시 공부하면서 많이 이해할 수 있었지만 아직도 헷갈린다 여려워..

시간 지나면 또 점점 까먹겠지 ㅠ

728x90
반응형
TAGS.

Comments