함수, 프로그래밍의 시작

💡함수의 정의와 호출

  • 함수의 정의 3가지 방식
    1. 함수 선언문
    2. 함수 표현식
    3. funtion 생성자 함수

💡1.함수 선언문

  • funtion키워드 함수명 (매개변수(=인자)) { return키워드 값반환 표현식; };
    funtion add(a,b){ return a+ b; };
  • 함수명 생략 불가,return문으로 결과값을 반환할 수 있다. 이를 반환값이라 한다.
  • 함수 호이스팅이 일어날 수 있기때문에 거의 사용하지 않는다.
  • 호이스팅 간단 설명 ✨
    : 함수 선언의 위치와는 상관없이 소스 내 어느 곳에서든지 호출이 가능하다.

💡2.함수 표현식

  • 함수의 일급객체 특성을 이용하여
    함수 리터럴 방식으로 함수를 정의하고 변수에 할당하는 것
//리터럴이란? ✨ : 값을 표기하는 약속된 기호,문자,방법이다.
1;				//정수리터럴
'Hello';		//문자열 리터럴
[1,2,3]; 		//배열 리터럴
{age:31};		//객체 리터럴
function(){}	//함수 리터럴
  • 익명 함수
    : 함수 표현식 방식으로 정의한 함수는 함수명을 생략할 수 있다. 이를 익명함수라 한다.
  • 기명 함수
    : 함수명을 정해준 함수.
// 기명 함수 표현식(named function expression)
var foo = function multiply(a, b) {
  return a * b;
};

// 익명 함수 표현식(anonymous function expression)
var bar = function(a, b) {
  return a * b;
};

console.log(foo(10, 5)); // 50

‼️주의‼️

  • 할당된 변수는 함수명이 아니라 할당된 함수를 가르키는 참조값을 저장함
  • 따라서 함수 호출시 기명함수의 함수명이 아니라
  • 함수를 가르키는 변수명을 사용해야한다.
  • 함수 표현식에서 사용한 함수명은 외부 코드에서 접근 불가능하기 때문이다.
  • 근데 함수 선언문에서는 함수명으로 호출해도 왜 에러가 나지 않았지?
  • 정답은 자바스크립트 엔진에 의해 함수표현식으로 형태가 변경되었기 때문!
  • 결과적으로 함수선언문도 함수표현식과 동일하게 함수 릴터럴방식으로 정의된 것이다.
//기명함수의 함수명으로 호출 시 에러뜸
console.log(multiply(10, 5)); // Uncaught ReferenceError: multiply is not defined

💡3. 생성자 함수

  • Funtion생성자 함수로 함수를 생성하는 방식은 일반적으로 사용하지 않는다.
//예시
let square = new Function('number','return number * number');
console.log(square(10))		//100

함수도 결국은 객체, 근데 이제 일급객체

💡메모리 주소를 '참조'한다.

  • 함수의 object가 heap이라는메모리에 저장
  • 함수의 이름은 결국 함수 오브젝트가 담겨있는 메모리 주소를 가르키고 있다.
    (=함수의 객체 주소를 가지고 있다.)
  • 함수를 다른 변수에 할당한 뒤 인자를 전달해주어도
    결과는 같다.
    왜냐,같은 메모리주소(=객체)를 참조하고 있기때문!
    (= 함수를 가리키는 참조값을 저장하고 있다.)
function add(a, b) {
  return a + b;
}
const sum = add;

console.log(sum(1, 2));		//3
console.log(add(1, 2));		//3

💡근데 이제 일급 객체임✨

  • 무명의 리터럴로 표현이 가능하다.
  • 변수나 자료구조(객체,배열...)에 저장할 수 있다.
  • 함수의 파라미터로 전달할 수 있다.
  • 반환값(return value)로 사용할 수 있다.

💡따라서 함수도 프로퍼티를 가진다

  • arguments 프로퍼티
    : 함수 호출 시 전달된 인수들의 정보를 담고있는 순회가능한 유사배열 객체이며 함수 내부에서 지역변수처럼 사용된다. 즉 함수 외부에서는 사용불가
    유사배열객체란? length 프로퍼티를 가진 객체, 배열은 아니므로 배열메소드 사용시 에러남
  • caller 프로퍼티
    : 자신을 호출한 함수를 의미
  • length 프로퍼티
    : 함수 정의 시 작성된 매개변수 갯수를 의미, arguments.length의 값과는 다를 수 있으므로 주의하여야 한다.
  • name 프로퍼티
    : 함수명을 의미, 기명함수는 함수명을 값으로 익명함수는 빈 문자열 값을 갖는다.
  • __proto__ 접근자 프로퍼티
    : 모든 객체는 프로토타입 내부슬롯을 가진다. 접근자 프로퍼티를 통해 자신의 프로토타입 객체에 접근할 수 있다.
  • prototype 프로퍼티
    : prototype 프로퍼티는 함수 객체만이 소유하는 프로퍼티이다. 즉 일반객체에는 prototype 프로퍼티가 없다. 생성자 함수가 생성한 인스턴스의 프로토타입 객체를 가르킨다.

함수의 파라미터

💡함수 파라미터(=매개변수)

  • 매개변수의 기본값은 무조건 undefined
  • 매개변수의 정보는 함수 내부에서 접근이 가능한 arguments 객체에 저장됨
  • 매개변수 기본값 Default Parameter를 정할 수 있다.
//매개변수(=인자,parameter)전달
function add(a = 1, b = 1) {	// 매개변수 기본값 a = 1, b = 1
  console.log(a);				//3
  console.log(b);				//4
  console.log(arguments);		//[Arguments] { '0': 3, '1': 4, '2': 5 }
  console.log(arguments[1]);	//4
  return a + b;
}
//인수(=argument)전달
console.log(add(3,4,5));		//7

💡나머지 매개변수 ...

  • 함수의 마지막 매개변수 앞에 "..."를 붙이면
  • 모든 후속 매개변수를 배열에 넣도록 지정합니다.
// Rest 매개변수 Rest Parameters
function sum(a, b, ...numbers) {
  console.log(a);			//1
  console.log(b);			//2
  console.log(numbers);		//[3, 4, 5, 6, 7, 8]
}
sum(1, 2, 3, 4, 5, 6, 7, 8);

함수의 반환값

💡함수의 return은 뭔데?

  • 함수는 자신을 호출한 코드에게 수행한 결과를 반환(return)할 수 있다.
    반환된 값을 반환값(return value)라고 부름.
  • return = undefined
  • 그냥 return만 있을 경우, 함수가 즉시 종료된다.
  • 만일 return 이후에 다른 구문이 존재할 경우,
    그 구문은 실행되지 않는다.
    사용 예 :
    조건이 맞지 않는 경우 함수 도입부분에서 함수를 일찍이 종료할 수 있다.

함수의 다양한 형태

💡즉시 실행 함수

  • 최초 한번만 호출되며 다시 호출 할 수 없다. 최초한번 실행 필효한 초기화 처리 등에 사용함
//즉시 실행 함수는 소괄호로 감싸준다.
(function () {
  // ...
}());

💡내부 함수

  • 함수 내부에 정의된 함수
  • 내부함수는 자신을 감싸는 부모 함수의 변수에 접근할 수 있다. 하지만 부모함수는 자식함수(내부함수)의 변수에 접근 불가
function parent(param) {
  let parentVar = param;
  function child() {
    let childVar = 'lee';
    console.log(parentVar + ' ' + childVar); // Hello lee
  }
  child();
  console.log(parentVar + ' ' + childVar);
  // Uncaught ReferenceError: childVar is not defined
}
parent('Hello');

💡재귀 함수

  • 자기 자신을 호출하는 함수
  • 재귀함수는 연쇄호출하므로 호출을 멈출 수 있는 탈출조건을 만들어야하며, 탈출조건이 없는 경우 스택오버플로우 에러 발생함
  • 대표적인 예시 팩토리얼
n! = n * (n - 1) * (n - 2) * ...*1

💡콜백 함수

  • 전달될 당시에 콜백함수를 바로 호출해서 반환된 값을 전달하는 것이 아니라
  • 콜백함수를 가리키고 있는 함수의 레퍼런스(참조값)가 전달된다.
  • 그래서 콜백함수는 고차함수안에서 필요한 순간에 호출이 나중에 됨
function double(num) {
  return num * 2;
}
// doubleNum 함수는 고차 함수이다. (다른 함수를 인자로 받음)
// doubleNum 함수의 인자 func에 함수가 들어올 경우
// func은 doubleNum의 콜백 함수이다.
function doubleNum(func, num) {
  return func(num);
}
// 아래의 경우 double은 doubleNum의 콜백 함수이다.
doubleNum(double, 5);

주의하기

💡함수내부에서 함부로 인자의 값변경은 💩

  • 함수내부에서 외부로부터 주어진 인자의 값을 변경하는 것은 💩
  • 상태변경이 필요한 경우에는, 새로운 상태를(오브젝트, 값) 만들어서 반환해야 함 ✨
  • 원시값 - 값에 의한 복사
  • 객체값 - 참조에 의한 복사 (메모리주소)
function display(num) {
  num = 5; // ❌
  console.log(num);
}
const value = 4;
display(value);
console.log(value);

function displayObj(obj) {
  obj.name = 'Bob'; // ❌❌❌❌❌❌ 외부로 부터 주어진 인자(오브젝트)를 내부에서 변경 ❌
  console.log(obj);
}
const ellie = { name: 'Ellie' };
displayObj(ellie);
console.log(ellie);

function changeName(obj) {
  return { ...obj, name: 'Bob' };
}

💡함수의 네이밍도 중요!

  • 함수가 수행하는 일을 잘 나타날수 있는 이름을 잘 짓는다.
  • 또한 매개변수의 이름도 의미있게 지어야 한다.
function fullName(firstName, lastName) {
  return `${firstName} ${lastName}`;
}
let lastName = '김';
let firstName = '지수';
console.log(fullName(firstName, lastName));		//지수 김 ✋
profile
냠소현 개발일지

0개의 댓글