[프론트엔드 스쿨 6기] 🗓️ 7월10일

유동균·2023년 7월 10일
0

프론트엔드 스쿨 6기

목록 보기
28/44
post-thumbnail

함수 표현식

자바스크립트는 함수를 특별한 종류의 값으로 취급합니다. 다른 언어에서처럼 "특별한 동작을 하는 구조"로 취급되지 않습니다.

함수 선언(Function Declaration)

function sayHi() {
  alert( "Hello" );
}

함수 표현식(Function Expression)

// 함수는 `값`으로 취급 된다 (= 변수에 할당할 수 있다)
// 함수를 복사해서 다른 변수에 넣을 수 있다
// 끝에 세미콜론 (함수 선언문은 X)
let sayHi = function() {
  alert( "Hello" );
};
// 자바스크립트는 괄호가 있어야만 함수가 호출
alert( sayHi );
function sayHi() {   // (1) 함수 생성
  alert( "Hello" );
}

let func = sayHi;    // (2) 함수 복사

func(); // Hello     // (3) 복사한 함수를 실행(정상적으로 실행됩니다)!
sayHi(); // Hello    //     본래 함수도 정상적으로 실행됩니다.
  • 본질은 값이기 때문에 값에 할 수 있는 일을 함수에도 할 수 있습니다.

  • 변수를 복사해 다른 변수에 할당하는 것처럼 함수를 복사해 다른 변수에 할당할 수도 있습니다.

콜백 함수

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function showOk() {
  alert( "동의하셨습니다." );
}

function showCancel() {
  alert( "취소 버튼을 누르셨습니다." );
}

// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);
  • 이름 없이 선언한 함수는 익명 함수(anonymous function) 라고 부릅니다. 익명 함수는 (변수에 할당된 게 아니기 때문에) ask 바깥에선 접근할 수 없습니다.
function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

ask(
  "동의하십니까?",
  function() { alert("동의하셨습니다."); },
  function() { alert("취소 버튼을 누르셨습니다."); }
);

함수 표현식 vs 함수 선언문

  1. 문법
// 함수 선언문
function sum(a, b) {
  return a + b;
}

// 함수 표현식
let sum = function(a, b) {
  return a + b;
};
  1. 언제 함수를 생성하는지
    함수 표현식은 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성합니다. 따라서 실행 흐름이 함수에 도달했을 때부터 해당 함수를 사용할 수 있습니다.

함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있습니다.

// 함수 선언문
sayHi("John"); // Hello, John

function sayHi(name) {
  alert( `Hello, ${name}` );
}

// 함수 표현식
sayHi("John"); // error!

let sayHi = function(name) {  // (*) 마술은 일어나지 않습니다.
  alert( `Hello, ${name}` );
};
  1. 스코프
    엄격 모드에서 함수 선언문이 코드 블록 내에 위치하면 해당 함수는 블록 내 어디서든 접근할 수 있습니다. 하지만 블록 밖에서는 함수에 접근하지 못합니다.
  • 함수 선언문
let age = prompt("나이를 알려주세요.", 18);

// 조건에 따라 함수를 선언함
if (age < 18) {

  function welcome() {
    alert("안녕!");
  }

} else {

  function welcome() {
    alert("안녕하세요!");
  }

}

// 함수를 나중에 호출합니다.
welcome(); // Error: welcome is not defined
  • 함수 표현식
let age = prompt("나이를 알려주세요.", 18);

let welcome;

if (age < 18) {

  welcome = function() {
    alert("안녕!");
  };

} else {

  welcome = function() {
    alert("안녕하세요!");
  };

}

welcome(); // 제대로 동작합니다.

arguments

let calculateTotal = function () {
  // 함수 안에서만 접근이 가능한 인수들의 집합 객체로서 배열과 유사한 형태를 가지고 있는 것 : arguments
  console.log(arguments);
};
const result = calculateTotal(1000, 500, 200, 6500, 100);

arguments 객체를 사용해 함수의 매개변수 없이 아이템의 총합을 구해보자

let calculateTotal = function () {
  // 함수 안에서만 접근이 가능한 인수들의 집합 객체로서 배열과 유사한 형태를 가지고 있는 것 : arguments

  // -----1번째 방법 for 문-----
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }

  // -----2번째 방법 for...of 문-----
  let total = 0;
  for (const key of arguments) {
    total += key;
  }

  // -----3번째 방법 forEach 빌려쓰기-----
  let total = 0;
  Array.prototype.forEach.call(arguments, function (item) {
    total += item;
  });

  // -----4번째 방법 유사배열을 slice를 빌려 서서 배열로 만드는 방법-----
  let total = 0;
  let realArray = Array.prototype.slice.call(arguments);
  realArray.forEach(function (item) {
    total += item;
  });

  // -----5번째 Array.from() 메서드를 이용해 유사배열을 배열로 만드는 방법-----
  // Object.prototype.toString() 인스턴스 메서드
  // Object.entries()            스태틱 메서드
  let total = 0;
  let realArray = Array.from(arguments);
  realArray.forEach(function (item) {
    total += item;
  });

  // -----6번째 spread syntax-----
  let total = [...arguments].reduce((a, b) => (a += b));
  let total = 0;
  let realArray = [...arguments];
  realArray.forEach(function (item, index, array) {
    total += item;
  });

  // -----7번째 배열 메서드 reduce() 이용하기-----
  let realArray = [...arguments];
  return realArray.reduce((acc, cur) => acc + cur, 0);
};

const result = calculateTotal(1000, 500, 200, 6500, 100);
console.log(result);

익명함수 함수 표현식

let anonymousFunctionExpression = function () {}; // 변수명이 함수명
console.log(anonymousFunctionExpression.name); // 함수도 객체다.

유명(이름을 가진) 함수 (표현)식

let namedFunctionExpression = function hello() {
  
};

호출할 때는 hello() 아니고 namedFunctionExpression()

콜백 함수 (표현)식

let callbackFunctionExpression = function(callback) {
  callback();
};

callbackFunctionExpression(
  function () {
    console.log('콜백 함수 실행');
  }
)

즉시 실행 함수

  • 함수 생성과 동시에 실행
  • 변수의 보호를 위해
  • 은닉화 Incapsulation(캡슐화)
(function(){
  console.log('즉시 함수');
})()

화살표 함수

함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법

// 일반 함수 표현식
let func = function(arg1, arg2, ...argN) {
  return expression;
};

// 화살표 함수
let func = (arg1, arg2, ...argN) => expression
  • 인수가 하나밖에 없다면 인수를 감싸는 괄호를 생략할 수 있습니다
  • 인수가 하나도 없을 땐 괄호를 비워놓으면 됩니다. 다만, 이 때 괄호는 생략할 수 없습니다.
  • 중괄호 안에 평가해야 할 코드를 넣어주어야 합니다. 그리고 return 지시자를 사용해 명시적으로 결괏값을 반환해 주어야 한다.
let sum = (a, b) => {  // 중괄호는 본문 여러 줄로 구성되어 있음을 알려줍니다.
  let result = a + b;
  return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해주어야 합니다.
};

사용

// () => {} 화살표 함수에는 argments 가 없다. 따라서 function(...){ argments }의 기능을 대신하는 (...rest) parameter를 사용해야 한다.
// 매개변수 밖에서 쓰면 기존의 spread syntax다.

let calcAllMoney = (a, b, ...args) => {
  // let total = 0;
  // args.forEach((item) => (total += item));

  return args.reduce((acc, item) => acc + i
                     
};
const result = calcAllMoney(1_000, 500, 200, 2_000);
console.log(result);

const result = calcAllMoney(1_000, 500, 200, 2_000);
일 때
let calcAllMoney = (...args) => {...}
여기서 ...args는 1000, 500, 200, 2000 모든 값이고

앞에 매개변수를 추가하게 된다면
let calcAllMoney = (a, b, ...args) => {...}
여기서 순차적으로 a가 1000, b가 500이 되면서 나머지 200과 2000이 ...args에 담기게 됩니다.

차이점

표현

// 함수 선언문
function normalFunction() {}

// 함수 표현식
const expressionFunction = function () {};

// 화살표 함수식
const arrowFunction = () => {};
// normalFunction, expressionFunction는 컨스트럭터가 없다. 즉, 함수로써의 기능만 수행한다. 따라서 가볍다.

/* 컨스트럭터란? 
function Button() {}
const a = Button();       // 리턴된 값이 a, 리턴값이 없다면 undefined
const b = new Button();   // new 키워드를 붙이면 b에는 객체가 담긴다.
new 기능을 컨스트럭터에서 지원한다.
즉, new 키워드를 붙여서 객체를 생성하는 생성자 함수가 되거나, 붙이지 않아 일반 함수가 되는데 이를 구분하기가 힘들기 때문에 arrowFunction에서는 컨스트럭터를 지원하지 않는다.
*/

this

// 함수 선언문
function normalFunction() {
  console.log(this);
}
normalFunction();
// 함수 표현식
const expressionFunction = function () {
  console.log(this);
};
expressionFunction();
// 화살표 함수식
const arrowFunction = () => {
  console.log(this);
};
arrowFunction();
  • 일반함수의 this는 나를 호출한 대상이지만, 화살표함수의 this는 자신의 부모를 가리킨다.
    • 화살표함수는 this를 바인딩하지 않는다.

0개의 댓글