TIL_this, call, apply, bind

김진경·2020년 3월 21일
0

IM19

목록 보기
3/21

this는 장소를 가리키는 것.

주소이다. 주소가 장소는 아니다.

https://www.youtube.com/watch?v=PAr92molMHU

Level 4-1. Javascript 심화 개념

this (2)

7분 ~ 15분

//this의 5가지 패턴
#1. global reference
this
> window {postMessage: f, blur: f, ....}

//#2 ~ #4에 쓰이는 함수
function bar(){
  console.log(this);
}

#2. function invocation
bar()
> window {postMessage: f, blur: f, ....}

#3. method invocation
window.bar()
> window {postMessage: f, blur: f, ....}

#4. construction mode
var barInstance = new bar();
> bar{}

#5. call, apply
//call 사용법
function bar(){
  console.log(this);
}

var obj = { hello: 'world'}
bar.call(obj)
> {hello: "world"}
bar.call({a: 1})
>{a: 1}
=======================================
//apply 사용법
var add = function (x, y){
  this.val = x + y;
}
var obj = {
  val: 0
};

add.apply(obj, [2, 8]);
console.log(obj.val); // 10
add.call(obj, 2, 8);
console.log(obj.val); // 10 // apply는 배열로, call은 쉼표로 넘긴다

------------------------

let arr = [10,2,3,4,7,23]
Math.max.apply(null, arr)
> 23
------------------------
//apply, call 사용시, this를 쓰지 않는 경우

function add(x,y){
  return x+y;
}

add.call(null, 2, 8) // this를 쓰지 않을 땐 null로 넘겨줘도 된다.
>10
add.apply(null, [2, 8]) // apply는 배열로
>10
  • 글로벌로 Jest 혹은 ESLint를 설치했다면 꼭 제거하자. 모든 프로젝트에 다 적용 될 수 있다.

함수 메소드

function add(x, y){
  this.val = x + y;
  console.log(this.val);
}

let obj = { val: 0 };
let boundFn = add.bind(obj, 2, 8);
BoundFn()

#1. call, apply
add.apply(obj, [2, 8]);
//10
add.call(obj, 2, 8);
//10

#2. bind
add.bind(obj, 2, 8);
//function add(x, y){
//this.val = x + y;
//console.log(this.val);
//}
BoundFn() // 10.function invocation처럼 보여서 window가 출력될 것 같지만 이미 this 값이 바인딩 돼있어서 10이 출력된다.

bind로 커링 구현하기

//커링이란 인자 n개를 받는 함수를 인자 1개로 받는 함수로 바꾸는 것.

function template(name, money){
  return '<h1>' + name + '</h1><span>' + money + '</span>';
}

>template('hoyong', 1000)
<"<h1>hoyong</h1><span>1000</span>"

let tmplSteve = template.bind(null, 'Steve'); 
// this 값을 위의 함수에서 사용하지 않았으므로 this를 사용하는 건 의미가 없다. 그래서 null을 넘겨주는 것.
// bind는 함수를 넘겨주고 그 함수의 name에는 'Steve'가 바인딩 되어있다.
>tmplSteve
< function template(name, money){
  return '<h1>' + name + '</h1><span>' + money + '</span>';
  }
>tmplSteve(100)
<"<h1>Steve</h1><span>100</span>"
>tmplSteve(300)
<"<h1>Steve</h1><span>300</span>"
//bind를 사용해서 인자 하나만 받는 함수들을 만들어냈다(커링)

1. Immersive Prep

this keyword (ES6)

4분

//function 내에서 this가 window가 아닌 주어진 값으로 적용되게 하는 법. 
function member(){
  return{
    first: 'Ingi',
    last: 'Kim',
    age: 40,
    printDetail: function(){
      getSalaryFromServer(function(salary){

        console.log(`Name: ${this.first} ${this.last}`);
        console.log(`Salary: ${salary}`);

      });
    }
  }
}

>var ingi = member();
<undefined
>ingi
<{first: "Ingi", last: "Kim", age: 40, printDetail: f}
>function getSalaryFromServer(callback){
  setTimeout(function(){
    callback(10000);
  }, 1000);
}
< undefined // 이 콜백함수는 function invocation이다.
> // 1초 후에 callback을 실행, 10000을 넘김
< undefined
> ingi.printDetail()
< undefined
  Name: undefined undefined // 이때 this는 window(function invocation이기 때문에). 그래서 상위 오브젝트를 따라가지 않음.
  Salary: 10000

어떻게 this.first를 'Ingi', 'Kim'으로 얻어낼 수 있을까.
=================================================
SOLUTION 1: USE bind

function member(){
a return{
    first: 'Ingi',
    last: 'Kim',
    age: 40,
    printDetail: function(){
      getSalaryFromServer(function(salary){

        console.log(`Name: ${this.first} ${this.last}`);
        console.log(`Salary: ${salary}`);

      }.bind(this)); 
// bind는 function을 리턴. call,bind는 첫번째로 this를 넘기는데 call은 바로 실행, bind는 this를 가진 채로 function을 리턴.
// 여기서 bind안의 this는 좌측 a부터 z까지의 오브젝트이다. 이 오브젝트가 ${this.first} <- 여기의 this로 바인딩됨. 그래서 해결 가능함.
    }
z }
}

=================================================
SOLUTION 2: USE ARROW FUNCTION

function member(){
1 return{
    first: 'Ingi',
    last: 'Kim',
    age: 40,
    printDetail: function(){
a     getSalaryFromServer((salary) => {

        console.log(`Name: ${this.first} ${this.last}`);
        console.log(`Salary: ${salary}`);

z     });
    }
9 }
}
//Arrow Function의 특징은 a부터 z사이에 excution context를 만들지 않는다. 
//그렇기에 ${this.first}의 this는 lexical한 상위 오브젝트(1부터 9)를 따라간다.

18분

//Arrow function 내에서의 this

var obj = {
  i: 10,
  b: () => console.log(this.i, this), // ?
  c: function(){
    console.log(this.i, this) // ?
  }
}

//function은 execution context를 만들고, Arrow function은 자체적으로 execution context를 만들지 않는다.

> obj.b
< undefined// 글로벌 영역에서 this는 window, window.i는 undefined.
  Window {postMessage: f, blur: f, ...}// this는 window 그 자체가 될 것.
> obj.c // function expression으로 감쌈. 그렇기에 이만큼({console.log(this.i, this) // ? })의 expression context를 가짐.
< 10 //method invocation의 형식에 따라 this는 obj가 되고, obj.i는 10이 됨.
  {i:10, b: f, c: f}//method invocation의 형식에 따라 this는 obj가 됨.

//Arrow function의 construction mode
var Foo = () => {};
var foo = new Foo(); // ?
> Uncaught TypeError: Foo is not a constructor
//Arrow function은 construction mode를 아예 할 수 없음. new 키워드가 필요할 땐 전통적인 function을 쓰거나 class 키워드를 사용.
profile
Maktub.

0개의 댓글