함수

김민수·2023년 10월 15일
0
post-thumbnail

1. 함수란?

일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 실행 단위로 정의한 것.

function add(x,y) // 함수 이름, 매개변수
	return x + y; // 반환값
}
add(2, 5)         // 인수

2. 함수를 사용하는 이유

  1. 코드의 재사용
  2. 유지보수의 편의성
  3. 실수를 줄여 코드의 신뢰성 향상
  4. 코드의 가독성 향상

3. 함수 리터럴

리터럴은 값을 생성하기 위한 표기법이다. -> 함수 리터럴도 평가되어 값을 생성하며, 이 값은 객체다.
즉, 함수는 객체다.

함수 vs 일반 객체

일반 객체함수
호출XO
고유한 프로퍼티XO

4. 함수 정의

변수는 선언 , 함수는 정의

함수정의 : 함수를 호출하기 전에 인수를 전달받을 매개변수, 실행할 문, 반환할 값을 지정하는 것

정의된 함수는 자바스크립트 엔진에 의해 평가되어 함수 객체가 된다.

함수 선언문

function add(x, y){return x + y}
  • 함수 이름을 생략할 수 없다.
  • 표현식이 아닌 문이다. 따라서 변수에 할당할 수 없어야 한다.
var add = function (x, y){return x + y}
  • 자바스크립트 엔진이 코드의 문맥에 따라 함수 리터럴을 해석하는 경우
  1. 표현식이 아닌 문인 함수 선언문으로 해석하는 경우

    함수 이름으로 호출 가능
    (자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당하기 때문)

  2. 표현식인 문인 함수 리터럴 표현식으로 해석하는 경우
    함수 이름으로 호출 불가능
    (함수 몸체 내에서만 참조 가능함)

함수는 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다.
즉, 암묵적으로 생성한 식별자를 호출하게 된다.

함수 표현식

  • 일급 객체 : 값의 성질을 갖는 객체
  • 자바스크립트의 함수는 일급 객체이므로 함수를 값처럼 자유롭게 사용할 수 있다.
  • 함수 리터럴로 생성한 함수 객체를 변수에 할당하는 방식을 함수 표현식이라 한다.
  • 함수 리터럴의 함수 이름은 생략이 가능하고, 익명 함수라고 한다.
var add = function test(x, y){return (x + y)}
console.log(add(1, 2))
console.log(test(1, 2)) // test is not defined
// 함수 이름이 아닌 함수 객체를 가리키는 식별자를 사용해야 한다.

함수 생성 시점과 함수 호이스팅

// 함수 참조
console.dir(add); // f add(x,y)
console.dir(sub); // undefined

// 함수 호출
console.log(add(2, 5)); // 7
console.log(sub(2, 5)); // TypeError


// 함수 선언문
function add(x, y) { return x + y };

// 함수 표현식
var sub = function (x, y) { return x - y };

함수 선언문은 런타임 이전에 함수 객체가 먼저 생성된다.
그리고 함수 이름과 동일한 이름으로 식별자를 생성하고 생성된 함수 객체를 할당한다.
즉, 코드가 실행되는 런타임시점에는 이미 함수 객체가 생성되어 있고 식별자에 할당까지 완료된 상태이다.
따라서 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하며 이를 함수 호이스팅이라고 한다.

  • 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출 가능하다.
  • 함수 표현식은 함수 호이스팅이 아닌 변수 호이스팅에 의해 undefined로 평가된다.

함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언해야 한다는 당연한 규칙을 무시하기 때문에 더글라스 크락포드는 함수 표현식을 더 권장한다.

Function 생성자 함수

var add = new Function('x','y','return x + y');
  • Function 생성자 함수로 함수를 생성하는 방식을 일반적이지 않으며 바람직하지 않다.
  • 클로저를 생성하지 않는 등, 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작한다.

화살표 함수 (ES6)

var add = (x,y) => x + y;
  • this 바인딩 방식이 다르고, prototype 프로퍼티가 없으면 arguments 객체를 생성하지 않는다.

5. 함수 호출

매개변수와 인수

function add(x, y){      // (x, y)  매개변수 : 함수를 정의할 때 선언
  console.log(arguments) 
  return x + y;          // (x + y) 반환값
}
add(2, 5)                // (2, 5)  인수 , 값으로 평가 될 수 있는 표현식
add(2)                   // 2 + undifined ==> NaN
add(2, 5, 1)             // 2 + 5 ==> 1  , arguments = 2, 5, 1

인수 확인

위와 같은 일이 발생할 수 있으니 매개변수 기본값을 사용하거나 단축 평가 등 사용하여 주의합시다

function add(x = 0, y = 0){
  return x + y;        
}
add(2, 5) // 7               
add(2)    // 2

매개변수의 최대 개수

  • 매개변수의 개수는 적을 수록 좋다. 3개 이상 넘어가면 객체 쓰는 것이 유리하다.
  • 이상적인 함수는 한가지 일만 해야하며, 가급적 작게 만들자!

반환문

  • 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다.
  • 반환문은 return 키워드 뒤에 오는 표현식을 평가한다. 지정하지 않을 경우는 undefined

6. 참조에 의한 전달과 외부 상태의 변경

function demonstrateSideEffects(value, obj) {
  // 원시 값에 대한 부수 효과 (변경되지 않음)
  value = 100;

  // 객체 참조 값에 대한 부수 효과 (원본 객체 변경)
  obj.name = "modified";
}

var num = 42;
var person = { name: "Alice" };

demonstrateSideEffects(num, person);

console.log(num); // 42 (원시 값이 변경되지 않음)
console.log(person.name); // "modified" (원본 객체가 변경됨)
  • 원시 값은 값 자체 복사, 객체는 참조 값이 복사된다.
  • 객체의 변경을 추적하려면 옵저버 패턴 등을 통해 추가 대응이 필요하다.
  • 깊은 복사를 통해 새로운 객체를 생성하고 재할당을 통해 교차한다.

7. 다양한 함수의 형태

즉시 실행 함수

함수 정의와 동시에 즉시 호출되는 함수

(function () {return 2 * 3 }());
  • 즉시 실행 함수 내에 코드를 모아 두면 혹시 있을 수도 있는 변수나 함수 이름의 충돌을 방지할 수 있다.

콜백 함수

함수가 자기 자신을 호출하는 것

  • 탈출 조건을 반드시 만들어야 한다.

중첩 함수

함수 내부에 정의된 함수

  • 외부 함수 내에서만 호출 될 수 있다.

콜백 함수

함수의 매개변수를 통해 다른 함수의 내부로 전달 되는 함수를 콜백 함수라고 한다.

고차 함수 : 매개 변수를 통해 함수의 외부에서 콜백 함수로 전달받은 함수


순수 함수와 비순수 함수

순수 함수 : 부수 효과가 없는 함수
비순수 함수 : 부수 효과가 있는 함수

var count = 0;

// 순수 함수
function increase(num) {
  return ++num;
}

// 비순수 함수
function decrease() {
  return --count;
}

count = increase(count); // 1
decrease(); // count = 0;

부수 효과를 최대한 억제하고 오류를 피하고 안전성을 높이자!

0개의 댓글