함수 선언(function declaration)

자바스크립트에서 함수는 다양한 방식으로 선언할 수 있는데, 가장 일반적인 방법은 function 키워드를 통해 함수를 선언하는 방식이고, 

// 함수 선언
function 함수이름(파라미터) {
  동작
  return; 리턴값
};

function sayHi() {
  console.log('Hi!');
};

다른 하나는 함수 선언을 변수에 할당하는 방식(함수 표현식 (function expression))이다. 

//함수 표현식
const printCode = function () {
  console.log('Code World!');
};

printCode();

 

자바스크립트에서 함수는 값으로 취급될 수도 있기 때문에 변수에 할당해서 함수를 선언할 수도 있다. 함수선언을 변수에 할당하는 모습만 함수 표현식이라고 오해할 수 있는데, 

// 변수에 할당해서 활용
const printJS = function () {
  console.log('JavaScript');
};

// 객체의 메소드로 활용
const codeLove = {
  printTitle: function () {
    console.log('Code');
  }
}

// 콜백 함수(callback function, 다른 함수의 파라미터에 전달된 함수)로 활용
myBtn.addEventListener('click', function () {
  console.log('button is clicked!');
});

// 고차 함수(higher order function, 변수에 호출된 값 할당해서 활용)로 활용
function myFunction() {
  return function () {
    console.log('Hi!?');
  };
};
//이중 괄호를 사용해서 고차함수를 바로 호출할수도 있다.
myFunction()();

파라미터로 함수를 선언해서 전달한 콜백함수로 활용하는 모습도 결과적으로는 함수선언을 값처럼 활용한다는 점에서 함수 표현식이라고 할 수 있다.

✅함수 표현식은 변수에 할당하는것이 포인트가 아니라 함수 선언을 값처럼 사용하는 방식이 포인트다.

함수 선언과 함수 표현식의 차이

//함수 선언
printCode(); //Welcome Coding World

function printCode() {
  console.log('Welcome Coding World');
};

함수 선언보다 먼저 함수를 호출했는데도 문제 없이 코드가 잘 동작한다. 선언문이 위쪽으로 끌어올려지는 현상을 호이스팅(Hoisting)이라고 한다.

//함수 표현식
printCode(); //ReferenceError

const printCode = function() {
  console.log('Welcome Coding World');
};

반면 함수 표현식은 변수 특성상 선언 이전에 접근할 수가 없다.

//함수 선언
function printCode() {
  function printJS() {
    console.log('JavaScript');
  }
  console.log('Hello Code World');
  printJS();
};

printCode(); //Hello Code World, JavaScript
printJS(); //ReferenceError

함수 선언은 변수의 var 키워드 처럼 함수 스코프를 가진다. 함수 안에 선언된 함수는 함수 밖에서 호출할 수 없지만 함수가 아닌 다른 코드블록에서 함수 선언을 하게 되면 모두 전역적으로 호출이 가능해진다.

//함수가 아닌 다른 코드블록에서 함수 선언을 해서 전역적으로 호출이 가능해진 모습
const x = 4;

if (x < 5) {
  function printJS() {
    console.log('JavaScript');
  }
};

{
  function printCode() {
    console.log('I love Coding');
  };
}

printCode(); //I love Coding
printJS(); //JavaScript

반면에 함수 표현식의 경우에는 할당된 변수에 따라 스코프(scope)가 결정된다.

var printJS = function () {
  console.log('JavaScript');
};

let printHi = function () {
  console.log('Hi');
};

const printCode = function () {
  conosole.log('Coding');
};
함수 선언 함수 표현식
-코드의 가독성
-변수 선언과 함수선언 명확하게 구분 가능
-함수 호출 자유로움
-반드시 선언 이후에 호출 가능
-가독성 good
-코드의 흐름 더 쉽게 파악 가능
-변수의 스코프도 활용 가능

일반적으로 개념을 설명할 때는 표현식보다 선언 부분이라는 의미가 좀 더 명확하게 구분되는 함수 선언이 보편적으로 사용된다.


파라미터(Parameter)의 기본 값

함수를 호출할때 함수의 밖에서 안쪽으로 다양한 값들을 전달받고자 한다면 파라미터를 활용해야한다.

자바스립트에서 함수의 파라미터는 할당 연산자로 기본값을 가질 수가 있다. 기본값이 있는 파라미터는 함수를 호출할 때 아규먼트를 전달하지 않으면, 함수 내부의 동작은 이 파라미터의 기본값을 가지고 동작하게 된다.

//  (name)이 파라미터이다.
function greeting(name) {
  console.log(`Hi! My name is ${name}!`);
}

//파라미터를 활용하면 전달하는 값에 따라서 다양한 결과로 동작하는 모습을 확인 할 수 있다.
greeting('Anna'); //Hi My name is Anna!
greeting('Tom'); //Hi My name is Tom!
greeting(); //Hi My name is Undefined!

// 파라미터 기본값
function sayHi(name = 'kelly') {
  console.log(`Hi! ${name}`);
}

sayHi('JavaScript'); // Hi! JavaScript
sayHi(); // Hi! kelly


//아규먼트가 파라미터로 전달될 때는 파라미터의 기본값과는 관계없이 함수를 호출할 때 작성한 순서 그대로 전달한다.
//때문에 기본값이 필요한 파라미터는 가급적 오른쪽에 작성하는것이 권장된다.
function greeting(name = 'Jenny', interest = 'Javascript') {
  console.log(`Hi! My name is ${name}!`);
  console.log(`I Like ${interest}!`);
};

greeting(undefined, 'Python'); //아규먼트가 undefined값으로 전달될 때도 동작한다.

//출력되는 값
Hi! My nmae is Jenny!
I Like Python!

arguments 객체

자바스크립트 함수 안에는 arguments라는 독특한 객체가 존재한다. arguments 객체는 함수를 호출할 때 전달한 아규먼트들을 배열의 형태로 모아둔 유사 배열 객체인데 특히, 함수를 호출할 때 전달되는 아규먼트의 개수가 불규칙적일 때 유용하게 활용될 수 있다.

function printArguments() {
  // arguments 객체의 요소들을 하나씩 출력
  for (const arg of arguments) {
    console.log(arg); 
  }
}

printArguments('Young', 'Mark', 'Koby');

‼️파라미터와 아규먼트를 헷갈릴 수도 있다. 하지만 꼭 구분지어서 알아두는 것이 좋다.

function greeting(name) { //함수 선언 부분에서 소괄호 안에 작성되는것이 파라미터
  console.log(`Hi My naame is ${name}!`);
};

greeting('Anna'); //함수 호출부분에서 파라미터로 전달하는 값에 해당하는 부분이 아규먼트
greeting('Jenny');
greeting('Tom');

Rest Parameter

arguments 객체를 이용하는 것 말고도 불규칙적으로 전달되는 아규먼트를 다루는 방법이 있다. 파라미터 앞에 마침표 세 개를 붙여주면, 여러 개로 전달되는 아규먼트들을 배열로 다룰 수 있다.
그리고 arguments객체는 유사 배열이기 때문에 배열의 메소드를 활용할 수 없는 반면, rest parameter는 배열이기 때문에 배열의 메소드를 자유롭게 사용할 수 있다는 장점이 있다.

function printArguments(...args) {
  // args 객체의 요소들을 하나씩 출력
  for (const arg of args) {
    console.log(arg); 
  }
}

printArguments('Young', 'Mark', 'Koby');

rest parameter는 다른 일반 파라미터들과 함께 사용될 수도 있는데

//앞에 정의된 parameter에 아규먼트를 먼저 할당하고 (first, second)
//나머지 아규먼트(...other)를 배열로 묶는 역할을 하기 때문에 
//일반 파라미터와 사용될때는 가장 마지막에 작성되어야 한다.
function printRankingList(first, second, ...others) {
  console.log('코드잇 레이스 최종 결과');
  console.log(`우승: ${first}`);
  console.log(`준우승: ${second}`);
  for (const arg of others) {
    console.log(`참가자: ${arg}`);
  }
}

printRankingList('Tommy', 'Jerry', 'Suri', 'Sunny', 'Jack');

이름 그대로 앞에 정의된 이름 그대로 앞에 정의된 파라미터에 argument를 먼저 할당하고 나머지 argument를 배열로 묶는 역할을 하기 때문에 일반 파라미터와 함께 사용할 때는 반드시 가장 마지막에 작성해야 한다.

Arrow Function

arrow function은 익명 함수를 좀 더 간결하게 표현할 수 있도록 ES2015에서 새롭게 등장한 함수 선언 방식이다. arrow function은 이름이 없는 익명함수이기 때문에 일반적으로 어떤 이름을 가진 변수에 할당하거나, 다른 함수의 아규먼트로 선언할 때 주로 활용된다.
아래 코드와 같이 표현식으로 함수를 정의할 때 활용될 수도 있고 콜백 함수로 전달할 때 활용할 수도 있다.

// 화살표 함수 정의
const getTwice = (number) => {
  return number * 2;
};

// 콜백 함수로 활용
myBtn.addEventListener('click', () => {
  console.log('button is clicked!');
});

화살표 함수는 기존의 function 함수를 조금 더 간결하게 표현하고자 등장했기 때문에 상황에 따라서는 훨씬 더 짧게 표현될 수도 있다.

// 1. 함수의 파라미터가 하나 뿐일 때
const getTwice = (number) => {return number * 2;};

// 파라미터를 감싸는 소괄호 생략 가능 (파라미터가 두개 이상이거나 없을 때는 반드시 소괄호를 작성)
const getTwice = number => {return number * 2;};

// 2. 함수 동작 부분이 return문만 있을 때
const sum = (a, b) => {return a + b;};

// return문과 중괄호 생략 가능 
// (하지만 함수 내부에서 조건문이나 반복문, 변수의 값을 할당하는 것과 같이 
// return문 외에 다른 표현들이 더 필요하다면 중괄호와 return 키워드는 생략할 수 없다.)
const sum = (a, b) => a + b;

// 3. 함수 내부 동작이 return문 하나뿐이어도 값이 객체인 경우는 주의해서 사용해야한다.
const getCode = () => {
  return {name: 'Ann', };
};

//중괄호와 return 키워드를 생략하게 되면 에러가 발생한다.
const getCode = () => {name: 'Ann', }; //Error

//객체라고 작성한 중괄호를 함수의 동작 부분을 구분하는 중괄호로 해석하기 때문이다. 이 땐 소괄호로 한번 더 감싸주면 해결된다.
const getCode = () => ({name: 'Ann', }); //{name: Ann}

그리고 Arrow function이 일반 함수와 몇 가지 차이점이 있는데 가장 대표적인 차이점은 arguments 객체가 없고, this가 가리키는 값이 일반 함수와 다르다는 것이다.

this

자바스크립트에는 this라는 조금 특별한 키워드가 있다. 웹 브라우저에서 this가 사용될 때는 전역 객체, Window 객체를 가지게 된다. 하지만 객체의 메소드를 정의하기 위한 함수 안에선 메소드를 호출한 객체를 가리킨다.

//이렇게 사용해도 잘 동작하지만 (물론 여기서 user을 this로 바꿔 사용해도 충분히 사용가능하다.)
const user = {
  firstName: 'Tess',
  lastName: 'Jang',
  getFullName: function () {
    return `${user.firstName} ${user.lastName}`;
  },
};

console.log(user.getFullName()); // Tess Jang

//이 메소드를 다른 객체에도 적용하고 싶어서 험수 외부로 분리하면 동작에 어려움이 있다.
function getFullName() {
  return `${user.firstName} ${user.lastName}`
};

const user = {
  firstName: 'Tess',
  lastName: 'Jang',
  getFullName: getFullName
};

const admin = {
  firstName: 'Alex',
  lastName: 'Kim',
  getFullName: getFullName
};

console.log(user.getFullName()); // Tess Jang
console.log(admin.getFullName()); // Tess Jang

//getFullName의 동작부분에서 user 객체만 바라보기 때문에 admin 객체에서 메소드를 호출하더라도 user 프로퍼티를 사용한다.

function getFullName() {
  return `${this.firstName} ${this.lastName}`
};

const user = {
  firstName: 'Tess',
  lastName: 'Jang',
  getFullName: getFullName
};

const admin = {
  firstName: 'Alex',
  lastName: 'Kim',
  getFullName: getFullName
};

console.log(user.getFullName()); // Tess Jang
console.log(admin.getFullName()); // Alex Kim

위 상황에선 this 키워드가 유용하게 사용될 수 있다. 자바스크립트에서 this는 함수를 호출한 객체를 가리키는 키워드인것이다. 그래서 코드를 작성할 때 값이 미리 결정되는게 아니라 함수가 호출될 때 어떤 객체가 그 함수를 호출했는지에 따라 상대적으로 값이 변하게 된다.

//일반 함수와 Arrow function은 this를 다루는 방식이 서로 다르다.

//화살표 함수에서 this 값은 일반 함수처럼 호출한 대상에 따라 상대적으로 변하는게 아니라
//화살표 함수가 실행되기 직전에 유효한 this 값과 똑같은 값을 가지고 동작한다.

console.log(this); //window객체가 호출된다.

const printThis = () => { //여기 화살표 함수가 선언되기 직전의 this는 윗줄에 window 객체이다.
  console.log(this);
};

const myObj = {
  cotent: 'myObj',
  printThis: printThis
};

const otherObj = {
  cotent: 'otherObj',
  printThis: printThis
};

myObj.printThis(); //window 객체
otherObj.printThis(); //window 객체, 그래서 코드를 실행했을 때 이런결과가 출력되는 것이다.

//이런 객체 특징때문에 객체에 메소드를 만들 때는 화살표 함수보다 일반 함수가 조금 더 권장된다.

'코린이 개념잡기 > JavaScript' 카테고리의 다른 글

Spread 구문  (0) 2024.12.16
조건부 연산자(삼항 연산자)  (0) 2024.12.16
null 병합 연산자 (??)  (0) 2024.12.15
AND와 OR 연산자 심화  (0) 2024.12.15
Falsy & Truthy  (1) 2024.12.15

+ Recent posts