화살표 함수, this, call/apply/bind 메소드, 구조 분해 할당

23031 단어 JavaScriptJavaScript

0. 인자와 파라미터

함수에서 값을 읽을때, 그 값들은 파라미터라고 부른다.
그리고 함수에서 값을 넣어줄 때, 그 값들은 인자라고 부른다.

const myFunction(a) { // 여기서 a 는 파라미터
  console.log(a); // 여기서 a 는 인자
}

myFunction('hello world'); // 여기서 'hello world' 는 인자

1. 화살표 함수

JavaScriptES6문법이며, 기존의 function문법을 대체하는 강력한 수단이다.
화살표 함수는 화살표와 인자로만 나타낼 수 있는데, return만 존재하는 함수라면 중괄호(curly bracket)까지 생략 가능하다.

//기존 function 문법
let data = function (x, y) {
  return x + ', ' + y;
}

//이를 화살표 함수로 나타내면,
let data = (x, y) => {
  return x + ', ' + y;
}

//return만 존재하는 함수이니 {}를 생략가능하다.
let data = (x, y) => x + ', ' + y;

//세 함수 모두 결과값이 같다.
data('Lee', 'A+') // -> 'Lee, A+'

이러한 화살표 함수의 특징은 클로저 함수(내부함수에서 외부함수로의 접근이 가능한 함수)를 표현할 때 유용하다.

let makeData = name => {
  return age => {
    return name + ': ' + age;
  }
}

//더 생략 가능하다.
let makeData = name => age => name + ': ' + age;

//둘 다 결과는 역시 동일하다.
makeData('Lee')(32) // -> 'Lee: 32'

2. this

  • this는 함수 실행시 호출(invocation) 방법에 의해 결정되는 특별한 객체이다. 함수 실행시 결정되므로, 실행되는 맥락(execution context)에 따라 this는 다르게 결정된다.

Method 호출 => this = 부모 객체 (실행 시점에 온점 왼쪽에 있는 객체)

obj.foo()

new 키워드를 이용한 생성자 호출 => this = 새롭게 생성된 인스턴트 객체

new Foo()
  • this를 이용해 작동하는 함수를 실행시킬 때, this를 명시적으로 결정해줄 수 있는 함수 메소드가 있는데, 그것이 call/apply/bind 메소드이다.

  • this는 화살표 함수로 표현시 사용하지 않는 것이 좋다고 한다. 화살표 함수에서의 this는 화살표 함수 외부 scope에 있는 객체를 참조하기 때문이다.

    화살표 함수는 block scope를 생성하며 function scope가 아니다.
    thisfunction scope에 의해 생기는데 Block scope는 자체 this를 가지지 않으므로
    화살표 함수를 쓸 때는 this를 쓰지 말자!
    반대로 말하면, this 쓸 땐 function 키워드를 쓰자

3. call, apply

  • call, apply, bind 메소드는 this를 명시적으로 지정해서 실행시키고 싶을 때 사용한다.

  • callapply는 함수 실행값을 return 하며, 첫 번째 인자는 항상 this값이다. 두 번째 인자부터는 함수의 인자를 명시하는데, call은 두 번째 인자부터 인자 하나하나를 ,(comma)를 이용해 나열하고, apply는 그 인자들을 배열형태로 나타낸다.

function add(x, y) {
  this.value = x + y;
  return this.value;
}

let result = { value: 0 }

//call메소드 사용예제.
add.call(result, 1, 2) // -> 3

//apply메소드 사용예제. 배열사용
add.apply(result, [1, 2]) // -> 3

callapply는 다른 메소드들을 빌려와서 사용하게도 해준다. 예를 들어, 유사 객체나 배열에 배열 메소드를 이용하고 싶을때(그냥은 사용할 수 없다), 그 프로토타입에 메소드를 붙여 유사배열을 this로 넘겨주면 사용가능하다!

let nodeList = document.querySelectorAll('div');
// -> 유사배열 nodeList[]

nodeList.forEach(function (el) { console.log(el) }) 
// -> TypeError 발생. 배열이 아닌 '유사'배열이기 때문.

//이런 nodeList라는 유사배열에 배열 메소드를 이용해 조작하고 싶다면,
Array.prototype.forEach.call(nodeList, function (el) { console.log(el) });
// -> 정상적으로 el을 조회할 수 있다!

4. bind

bind메소드는 함수의 this값을 넘겨주지만, 함수가 실행되지는 않으며, 함수 그 자체를 리턴한다.
bind메소드는 DOM에서 이벤트에 함수를 할당할 때 (함수 자체를 넘겨줄 때) this를 바인딩하여 활용할 수 있다.

function add(x, y) {
  this.value = x + y;
  return this.value;
}

let result = { value: 0 }

//bind메소드 예제.
add.bind(result) // -> add함수 자체를 리턴. this에는 result가 바인딩 되었다.

//result를 바인딩 한 후, 함수를 실행하면,
add(5, 6) // -> 11

혹은 setTimeout()으로 시간 지연을 일으 킨 후 함수를 비동기적으로 실행할 때 활용할 수 있으며, 이 메소드는 항상 window객체를 this 바인딩하는 특징이 있다.

printAsync() {
  // 1초 후 사각형의 넓이를 콘솔에 표시합니다
  setTimeout(this.printArea.bind(this), 2000)
}

5. spread/rest

  • spread
    이 문법을 사용하면, 객체 혹은 배열을 펼칠 수 있다.
    기존의 것을 건들이지 않고, 새로운 객체를 만든다는 것인데, 이러한 상황에 사용 할 수 있는 유용한 문법이 spread 이다.
const slime = {
  name: '슬라임'
};

const cuteSlime = {
  ...slime,
  attribute: 'cute'
};

spread 문법을 사용하면, 배열의 값을 모두 파라미터로 넣을 수 있다.

function sum(...rest) {
  return rest.reduce((acc, current) => acc + current, 0);
}

const numbers = [1, 2, 3, 4, 5, 6];
const result = sum(...numbers);
//배열의 모든 원소를 spread로 넣을 수 있다.
console.log(result);
  • rest

객체에서의 활용

const purpleCuteSlime = {
  name: '슬라임',
  attribute: 'cute',
  color: 'purple'
};

const { color, ...cuteSlime } = purpleCuteSlime;

배열에서의 활용

const numbers = [0, 1, 2, 3, 4, 5, 6];

const [one, ...rest] = numbers;

함수에서의 활용

함수의 파라미터가 몇개가 될 지 모르는 상황에서 rest 파라미터를 사용하면 매우 유용하다.

function sum(...rest) {
//알 수 없는 파라미터의 갯수에 활용
  return rest;
}

const result = sum(1, 2, 3, 4, 5, 6);
console.log(result);

6. 구조 분해

구조 분해 할당은 Spread 문법을 이용하여 배열이나 객체 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정을 말한다.
아래에 함수에서 구조 분해를 활용하는 코드를 나타내었다.

function whois({displayName: displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

let user = {
  id: 42,
  displayName: "jdoe",
  fullName: {
      firstName: "John",
      lastName: "Doe"
  }
};

whois(user) // "jdoe is John

좋은 웹페이지 즐겨찾기