Vana Blog

(ES6)learning javascript - 함수

February 14, 2019

함수

하나의 단위로 실행되는 문의 집합. 모든 함수에는 바디가 있다. 함수 바디는 함수를 구성하는 문의 모음.

반환 값

함수 호출의 값 함수 바디 안에 return 키워드 사용. return을 명시적으로 호출하지 않으면 반환 값은 undefined가 된다.

호출과 참조

자바스크립트에서는 함수도 객체.

getGreeting(); // 함수 호출
const greetingFn = getGreeting;
greetingFn; // 함수 참조 function getGreeting()
 
// 함수를 객체 프로퍼티에 할당
const o = {};
o.f = getGreeting;
o.f();
 
// 배열 요소로 할당
const arr = [1, 2, 3];
arr[1] = getGreeting;
arr[1]();

함수와 매개변수

function avg(a, b) {
  return (+ b)/2;
}

여기서 a, b가 매개변수

  • 함수 안에서 매개변수에 값을 할당해도 함수 밖에 있는 변수에 아무런 영향이 없다. 같은 이름의 변수이지만 다름.
  • 하지만 함수 안에서 객체 자체를 변경하면 그 객체는 함수 밖에서도 바뀐 것이 반영된다.

    tip. value type을 전달할 때는 값이 복사되나, 객체는 참조 타입(reference type)이므로 객체를 전달할 때는 같은 객체를 가르킨다.

매개변수 해체

객체, 배열 가능, 확산 연산자 사용하여 남는 매개변수를 이용 가능

function getSentence({ subject, verb, object }) {
  return `${subject} ${verb} ${object}`;
}
 
const sentence = {
  subject: 'I',
  verb: 'love',
  object: 'you'
};
 
getSentence(sentence); // I love you
  • 해체 할당과 마찬가지로 프로퍼티 이름은 반드시 유효한 식별자여야 하고, 들어오는 객체에 해당 프로퍼티가 없는 변수는 undefined를 할당받는다.
  • 배열 역시 해체할 수 있다.

    tip. ES5에서는 함수 바디 안에서만 존재하는 특별한 변수 arguments를 사용해서 확산과 비슷한 일을 할 수 있다. arguments는 실제 배열이 아니라 배열 비슷한 객체이다.

매개변수 기본값

ES6에 추가된 기능 일반적으로 매개변수 값을 제공하지 않으면 undefined로 값이 할당됨.

function setDefault(a, b = 'default', c = 3) {
  return `${a} - ${b} - ${c}`;
}
setDefault(5, 6); // 5 - 6 - 3
setDefault(5); // 5 - default - 3

객체의 프로퍼티인 함수

객체의 프로퍼티인 함수를 메서드라고 불러 일반적인 함수와 구별함.

const o = {
  name: 'Wallace',
  bark: function() {return 'Woof!';} // 함수 프로퍼티(메서드)
}
 
const o = {
  name: 'Wallace',
  bark() {return 'Woof!';} // 함수 프로퍼티(메서드)
}

this 키워드

자바스크립트에서의 this는 메서드를 호출하면 this는 호출한 매서드를 소유하는 객체가 됨.

const o = {
  name: 'Wallace',
  speak() {return `My name is ${this.name}.`}
}

o.speak()를 호출하면 this는 o에 묶인다.

  • this는 어떻게 호출했느냐에 다라 달라진다. this가 o에 묶인 이유는 speak가 o의 프로퍼티여서가 아니라 o에서 speak를 호출했기 때문이다.

함수 표현식과 익명 함수

함수 표현식은 함수 이름을 생략할 수 있다. 함수 선언과 문법적으로 같음.

const g = function f() {
 // 
}

밖에서 함수 호출할 때에는 g()로 해야하나 f()로 할 경우 에러가 난다.
왜 이렇게 쓰냐하면 함수 안에서 자신을 호출할 때(재귀) 이런 방식이 필요하다.

const g = function f(stop) {
  if(stop) console.log('stop');
  f(true);
}

함수 선언과 함수 표현식의 차이는 컨텍스트에 있다.

화살표 표기법

function 이라는 단어와 중괄호 숫자를 줄이려고 고안된 단축 문법.

  • function 생략
  • 함수에 매개변수가 단 하나 뿐이라면 ()도 생략할 수 있다.
  • 함수 바디가 표현식이 하나라면 중괄호와 return문도 생략할 수 있다.
const f1 = function() {
  return 'hello!';
};
const f1 = () => 'hello!';
f1();
 
const f2 = function(name) {
  return `hello ${name}!`;
};
const f2 = name => `hello ${name}!`;
f2();
 
const f3 = function(a, b) {
  return a + b;
};
const f3 = (a, b) => a + b;
f3();
  • 중요!!! 화살표 함수는 this가 다른 변수처럼 정적(lexically)으로 묶인다 -> 내부 함수 안에서만 this 사용 가능.
  • 화살표 함수는 객체 생성자로 사용할 수 없다.
const o = {
  name : 'Julie',
  greetBackwards: function() {
    const getReverseName = () => {
      let nameBackwards = '';
      for(let i=this.name.length-1; i>=0; i--){
        nameBackwards += this.name[i];
      }
      return nameBackwards;
    };
    return `${getReverseName()} si eman ym ,olleH`;
  }
}
o.greetBackwards(); // "eiluJ si eman ym ,olleH"

call과 apply, bind

자바스크립트에서는 일반적인 방법 외에도, 함수를 어디서, 어떻게 호출했느냐와 관계없이 this가 무엇인지 지정할 수 있다.

call 메서드는 모든 함수에서 사용할 수 있으며, this를 특정 값으로 지정할 수 있다.

const bruce = { name: 'Bruce' };
// 이 함수는 어떤 객체와도 연결되지 않았지만 함수 내부에서 this를 사용한다.
function greet() {
  return `Hello ${this.name}!`;
}
 
greet(); // this는 undefined.
greet.call(bruce); // this는 bruce.
 
function update(birthYear, occupation) {
  this.birthYear = birthYear;
  this.occupation = occupation;
  console.log(bruce);
}
update(bruce, 1949);

함수를 호출하면서 call을 사용하고 this로 사용할 객체를 넘기면 해당 함수가 주어진 객체의 메서드인 것처럼 사용할 수 있다.

apply는 함수 매개변수를 처리하는 방법을 제외하면 call과 완전히 같다.

apply는 매개변수를 배열로 받는다는 차이점이 있다.

update.apply(bruce, [1955, 'actor']);

apply를 설명할 때 흔히 사용하는 예제는 배열의 최솟값과 최댓값을 구하는 예제.

const sortArr = [2, 3, -5, 15, 7];
// Math.min, Math.max 는 this와 관계없이 동작해서 this를 null로 사용
Math.min.apply(null, sortArr); // -5
Math.max.apply(null, sortArr); // 15

그러나 Math는 this 값이 무엇이든 상관없어서 apply안쓰고 확산 연산자 사용으로 쓰는게 편함.

Math.min(...sortArr);

bind를 사용하면 this값을 영구히 바꿀 수 있기때문에 주의해야한다.


Vana Yun

Written by Vana Yun