[JS] Higher-Order Functions, The call and apply bind Methods

Hyodduru ·2021년 12월 14일
0

JavaScript

목록 보기
38/60
post-thumbnail

Functions Accepting Callback Functions

const oneWord = function (str) {
  return str.replace(/ /g, '').toLowerCase();
};

/ /g 기억하기! select all of the spaces

const upperFirstWord = function (str) {
  const [first, ...others] = str.split(' ');
  return [first.toUpperCase(), ...others].join(' ');
};


const transformer = function (str, fn) {
  console.log(`Original string : ${str}`);
  console.log(`Transformed string: ${fn(str)}`);
  console.log(`Transformed by: ${fn.name}`);
};
// 위 함수는 어떻게 string이 transform 되는지 신경쓰지 않는다. 
//오직 transform 하는 부분만 신경씀. 
//관련 code를 다른 함수들로 abstract함. 
//=> created a new level of abstraction

transformer('JavaScript is the best!', upperFirstWord);
//Original string : JavaScript is the best!
//Transformed string: JAVASCRIPT is the best!
//Transformed by: upperFirstWord
transformer('JavaScript is the best!', oneWord);
//Original string : JavaScript is the best!
//Transformed string: javascriptisthebest!
//Transformed by: oneWord

위의 transformer 함수는 Higher-order function이다. why? this function operates at a higher level of abstraction leaving the low level details to this low level functions.

oneWord, upperFirstWord => lover-level functions with lower level abstraction

const high5 = function () {
  console.log('✋🏻');
};
document.body.addEventListener('click', high5);
// addEventListener : higher-order function, high5 : callback function

['Jonas', 'Martha', 'Adam'].forEach(high5); //✋🏻가 세번 출력된다.

매우매우 중요) JS uses callbacks all the time why? makes it easy to split up or code into more reusable and interconnected parts, allows us to create abstraction.

  • abstract : we hide the detail of some code implementation because we don't really care about all that detail.

    정리) abstraction(추상화) : 프로그램에서 필요한 요소만을 사용해서 객체를 표현하는 것! 내부 구현은 복잡한데 실제로 노출되는 부분은 단순하게 만든다는 개념. 프로그래밍은 추상화의 연속. 목적을 명확히! 불필요한 것들은 숨기기! 핵심만 드러내기!

Functions Returning Functions

const greet = function (greeting) {
  return function (name) {
    console.log(`${greeting} ${name}`);
  };
};

const greeterHey = greet('Hey');
greeterHey('Jonas'); //Hey Jonas
greeterHey('Steven'); //Hey Steven

greet('Hello')('Jonas'); //Hello Jonas

//Arrow function
const greetArr = greeting => name => console.log(`${greeting} ${name}`);

greetArr('Hi')('Jonas'); //Hi Jonas

The call and apply Methods

const lufthansa = {
  airline: 'Lufthansa',
  iataCode: 'LH',
  bookings: [],
  book(flightNum, name) {
    console.log(
      `${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`
    );
    this.bookings.push({ flight: `${this.iataCode} ${flightNum}`, name });
  },
};

lufthansa.book(239, 'Jonas Schmedtmann'); //Jonas Schmedtmann booked a seat on Lufthansa flight LH239
lufthansa.book(635, 'John Smith'); //John Smith booked a seat on Lufthansa flight LH635
console.log(lufthansa);
// this = lufthansa

const eurowings = {
  airline: 'Eurowings',
  iataCode: 'EW',
  bookings: [],
};

const book = lufthansa.book; // 이와 같은 표기 갸능함 why? JavaScript는 first class function 가지고 있으므로!

//book(23, 'Sarah Williams'); // error why? 이 함수는 a regular function call. 
// In a regular function call, the this keywords points to undefined! (strict mode에서)

Call method

call은 function의 method
call을 부름으로써 첫번째 인자 eurowings에 book함수 내에 있는 this를 부여한다.
call method는 명확하게 어떤 object를 this로 할 것인지를 명시해주는 역할을 한다.

book.call(eurowings, 23, 'Sarah Williams'); // Sarah Williams booked a seat on eurowings flight EW23

console.log(eurowings);
// bookings : [{flight: "EW 23",name: "Sarah Williams"}] 추가됌!

book.call(lufthansa, 239, 'Mary Cooper');
console.log(lufthansa);

const swiss = {
  airline: 'Swiss Air Lines',
  iataCode: 'LX',
  bookings: [],
};

book.call(swiss, 583, 'MaryCooper');
console.log(swiss);

Apply method

call과 하는 일은 같음. call과의 차이점 : a list of arguments(ex 583, 'MaryCooper')를 받지 않는다. 그 대신 an array of arguments를 받는다.
modern js 에서 더이상 apply method는 쓰이지 않는다.

const flightData = [583, 'George Cooper'];
book.apply(swiss, flightData);
console.log(swiss);

book.call(swiss, ...flightData); // Modern JS (apply와 똑같음)

The bind Method

bind method는 바로 함수를 부르지 않는다. Instead it returns a new function where this keyword is bind.

const bookEW = book.bind(eurowings); // book 함수를 부르지 않음. 
//This will return a new function where this keyword will always be set to Eurowings.
const bookLH = book.bind(lufthansa);
const bookLX = book.bind(swiss);

bookEW(23, 'Steven Williams'); //Steven Williams booked a seat on Eurowings flight EW23
const bookEW23 = book.bind(eurowings, 23);
bookEW23('Jonas Schmedtmann'); //Jonas Schmedtmann booked a seat on Eurowings flight EW23
bookEW23('Martha Cooper'); // Martha Cooper booked a seat on Eurowings flight EW23

//const bookEW23 = book.bind(eurowings, 23, 'Jonas'); 와 같은 형태도 가능

위와 같이 arguments의 일부만 적은 것을 partial application이라고 함.

  • partial application ? a part of the arguments of the original function are already applied, so which means, already set.

With Event Listeners

lufthansa.planes = 300;
lufthansa.buyPlane = function () {
  console.log(this);
  this.planes++;
  console.log(this.planes);
};

lufthansa.buyPlane(); //this = lufthansa / 301

 document.querySelector('.buy').addEventListener('click', lufthansa.buyPlane);
// 여기서 this는 .buy element를 가리킨다. event listner에서 callback 함수 내의 this는 element 자체를 가리킨다.  this Keyword 매우 동적.

수동적으로 this를 가르킬 object를 설정해주기 위한 방법

document
  .querySelector('.buy')
  .addEventListener('click', lufthansa.buyPlane.bind(lufthansa));
// this = lufthansa

Partial application

means that we can preset parameters.


const addTax = (rate, value) => value + value * rate;
console.log(addTax(0.1, 200));

// this가 따로 없기때문에 null이라 적어줌
const addVAT = addTax.bind(null, 0.23);

console.log(addVAT(100)); //123

const addTaxRate = function (rate) {
  return function (value) {
    return value + value * rate;
  };
};
const addVAT2 = addTaxRate(0.23);
console.log(addVAT2(100)); //123
profile
꾸준히 성장하기🦋 https://hyodduru.tistory.com/ 로 블로그 옮겼습니다

0개의 댓글