[JS-책 편김에 끝까지] 함수

짱쫑·2023년 2월 10일
0

javascript

목록 보기
5/10
post-thumbnail

함수 function ⭐️ ⭐️ ⭐️

수학의 함수는 입력(input)을 받아 출력(output)을 내보내는 일련의 과정을 정의한 것이다. 프로그래밍 언어의 함수도 결이 같다. 즉, 특정한 일을 수행하는 코드의 집합이다.

프로그래밍 언어의 함수는 일련의 과정을 문(statement)로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다.

function 이라는 함수 정의 키워드를 먼저 작성하고 어떤 일을 수행하는지 한눈에 알기 쉬운 함수 이름을 작성한 뒤 외부에서 전달받을 수 있는 매개변수(혹은 인자, parameter) 받아와서 특정한 일을 수행한 후 return이라는 키워드를 통해서 처리한 값을 외부로 다시 반환할 수 있다. 이러한 것을 '함수 정의'라고 한다. 그리고 정리된 함수를 함수의 이름을 통해서 호출(function call/invoke)할 수 있는데 호출을 할 때 인수를 넣을 수 있는데 이때 인수(argument)는 함수의 매개변수에 전달된다.

  • 함수도 결국 객체이기 때문에 함수를 정의하면 함수의 오브젝트가 heap에 할당되고, 함수의 이름은 객체가 담긴 메모리 주소를 가리키게 된다. 그래서 함수의 이름은 함수를 참조하고 있음을 알 수 있다.

    // 기본 사용
    function sum(a, b) {
        return a + b;
    }
    const result = sum(1, 2);
    console.log(result); //3
    
    // 예제2
    let lastName = '짱';
    let firstName = '쫑';
    let fullName = `${lastName} ${firstName}`
    console.log(fullName); // 짱 쫑
    
    let lastName2 = '김';
    let firstName2 = '수지';
    let fullName2 = `${lastName} ${firstName}`
    console.log(fullName2); // 김 수지
    
    // 한국에서는 이름을 성부터 나오게 하지만 외국에서는 이름이 먼저 와야하는 경우 하나하나 변경해야 하는 번거로움이 있다. 그런 번거로움을 해소하기 위해서 함수를 이용할 수 있다.
    
    function fullName(firstName, lastName) {
        return `${firstName} ${lastName}`;
    }
    let lastName = '짱';
    let firstName = '쫑';
    console.log(fullName(firstName, lastName)); // 쫑 짱
    
    let lastName2 = '김';
    let firstName2 = '수지';
    console.log(fullName(firstName2, lastName2)); // 수지 김
    
    // 이렇게 하나하나 수정하지 않고, 함수에서 한곳만 수정하면 되기 때문에 효율적이고 편해진다. 

함수와 메모리

앞서 함수를 정의하게 되면 heap에 할당되고, 함수의 이름은 객체가 담긴 메모리의 주소를 가리킨다고 했다.

function add(a, b) {
	return a + b;
}
const sum = add;

예시 코드에서 add라는 함수를 정의했다. 여기서 add함수의 코드 블럭은 메모리 어딘가에 저장이 되고 add라는 함수명은 코드블럭이 담긴 메모리 주소를 가리키게 된다. 엄밀히 말하면 가리킨다는 말보다는 add라는 함수이름은 0x11(예시)이라는 주소를 가리키고 0x11에는 코드블럭이 담긴 주소 0x001(예시)가 담겨있다. 그 다음 sum이라는 새로운 변수에 add라는 함수 이름을 할당하는 것은 add가 가리키고 있는 메모리 주소를 그대로 할당하는 것이된다. 그럼 sum이라는 변수도 0x11이라는 메모리 주소를 가지고 있는 것이다. 정리하면 add와 sum 은 { return a + b; } 동일한 함수 정의를 가리키고 있다. 그래서 똑같이 둘 다 함수처럼 호출 할 수 있다.

function add(a, b) {
	return a + b;
}
const sum = add;

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

요는 함수 이름 자체는 함수를 가리키고 있는 변수와 동일하고 함수 이름을 어딘가에 할당한다는 것은 함수를 가리키고 있는 그 메모리 주소를 복사해서 할당하는 것과 동일하다. 그래서 함수의 이름 자체는 함수를 가리키고 있는 것이다.

반환 return

함수는 return이라는 키워드를 통해 실행 결과를 외부로 반환할 수 있다.
함수에서 return을 작성하지 않으면 자바스크립트 엔진은 디폴트 값으로 undefined를 반환한다.

function add(a, b) {
	return a + b;
}
const result = add(1,2);
console.log(result); // 3

function add(a, b) {
	// return문 없음
}
console.log(add()); // undefined

// 만약 단순히 무언가 print하는 기능이라면 return을 생략해도 된다.
function print(text) {
	console.log(text);
}
print('text'); // text

// 이러한 함수는 어떤값도 반환하지 않는 함수이기 때문에 return을 받는 것처럼 작성할 필요가 없다
const outcome = print('text'); // undefined

반환문의 역할은 두 가지가 있다. 첫 번째는 함수의 실행을 중단하고 함수 몸체를 빠져나간다. 반환문 이후에 다른 문이 존재한다면 그 문은 실행되지 않고 무시된다. 다시말해 반환문은 특정한 과정을 실행한 후 함수를 종료한다는 의미다.

function multiply(x, y) {
	return x * y;
  console.log('콘솔에 찍힐까?'); // 무시 됨
}
console.log(multiply(3, 5)); // 15

// ! return문을 작성할 때는 ; 세미콜론의 위치가 중요하다
function multiply(x, y) {
	// return 키워드와 반환값 사이에 줄바꿈이 있다면 세미콜론 자동 삽입(ASI)에 의해 세미콜론이 추가되고 반환값의 코드는 무시된다.
	return; // 함수 종료
  x * y; // 무시 됨
}
console.log(multiply(3, 5)); // undefined

다른 하나는 먼저 설명했던대로 return을 명시적으로 지정하지 않으면 undefined가 반환된다는 것이다.

// 예제 3, 파라미터의 숫자가 양수일때만 출력하고 싶을 때
function print(num) {
	if (num < 0) {
  	return; // 파라미터가 음수면 함수 종료
  }
  console.log(num);
}
print(12); // 12
print(-12); // undefined

// return;은 return undefined;이라고 보면 된다.
// 예제는 간단하지만 함수가 무거운 로직을 수행하기 이전에 함수가 수행할 조건과 인자의 유효성을 검사하는 것도 중요하다!

인자 parameter

함수를 실행하기 위해 필요한 값을 함수 외부에서 함수 내부로 전달할 필요가 있는 경우 매개변수(parameter)를 통해 인수(argument)를 전달하는데 인수는 값으로 평가될 수 있는 표현식이어야 한다.

매개변수는 함수를 정의할 때 선언하고 함수 몸체 내부에서 변수와 동일하게 취급된다. 즉, 함수가 호출되면 함수 몸체 내에서 암묵적으로 매개변수가 생성되고 일반 변수와 마찬가지로 undefined로 초기화된다. 다시말해 매개변수의 기본값은 무조건 undefined란 말이다.

function add(a, b) {
	console.log(a);
  console.log(b);
  return a + b;
}
add(1, 2); // 1 2
add(1, 2, 3); // 1 2 추가적으로 값을 전달하면 무시된다.
add(2); // NaN 첫 번째 매개변수에는 2가 할당 되지만 두 번째 매개변수에는 아무것도 할당되지 않으므로 2 + undefined인 셈이다. 그러므로 NaN이 반환된다.

function add(a, b) {
	console.log(arguments);
  return a + b;
}
add(1, 2); // [Arguments] { '0': 1, '1': 2 }
// arguments를 이용하면 전달된 인자를 확인할 수 있다.
// arguments는 index가 0부터 시작하는데, 0은 첫번째 1은 두번째와 같은 순서다.
// 즉, 첫 번째 인자에는 1이 두 번째 인자에는 2가 전달되고 이것들이 a와 b로 맵핑이 되어 있음을 알 수 있다.
// arguments는 배열처럼 접근이 가능하다
console.log(arguments[0]); // 1
console.log(arguments[1]); // 2
  • 매개변수의 기본값

    // 매개변수의 정보는 함수 내부에서 접근이 가능한 arguments 객체에 저장됨
    
    // 매개변수의 기본값 설정(default parameter)
    function add(a = 1, b = 1) {
    	return a + b;
    }
    console.log(add()); // 2
    // 그러나 add(2, 3)과 같이 인수를 전달하게 되면 기본값은 무시된다.
  • Rest 매개변수 Rest Parameters

몇개의 인자를 받을지 모르는 상황에서 모든것들을 배열로 받고 싶을 때 Rest Parameter를 쓸 수 있다.

function sum(...numbers) {
	console.log(numbers);
}
sum(1, 2, 3, 4, 5, 6, 7, 8); // [1, 2, 3, 4, 5, 6, 7, 8]

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);

함수 표현식 expression

자바스크립트의 함수는 객체 타입의 값이고 함수는 값처럼 변수에 할당할 수도 있고 프로퍼티 값이 될 수도 있으며 배열의 요소가 될 수도 있다. 이처럼 값의 성질을 갖는 객체를 일급 객체라 한다. 즉, 자바스크립트의 함수는 일급 객체다. 함수가 일급 객체라는 것은 함수를 값처럼 자유롭게 사용할 수 있다는 의미다.

함수는 일급 객체이므로 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있는데 이러한 함수 정의 방식을 함수 표현식이라 한다.

let add = function (x, y) {
	return x + y;
}
console.log(add(2, 5)); // 7

// 함수의 이름이 없는 것을 무명의 함수, 무명함수라고 한다.

let add = function sum(x, y) {
	return x + y;
}
console.log(sum(2, 5)); // ReferenceError: sum is not defined

// 이름을 써줘도 상관은 없지만 함수가 정의되고 add에 할당되는 거라 sum이라는 이름은 존재하지 않게된다.
// 그렇기에 이런경우는 보통 함수의 이름을 생략한다.

화살표 함수 arrow function ⭐️ ⭐️ ⭐️

  • const 이름 = (매개변수) => { }

    add = (a, b) => {return a + b };
    console.log(add(1, 2)); // 3
    
    // 코드안에서 특별한 로직이 없이 값만 return하는 경우라면 return과 { }를 생략할 수 있다.
    add = (a, b) => a + b;

즉시 실행함수 IIFE Immediately-Invoked Function Expressions

함수의 정의와 동시에 즉시 호출되는 함수를 말하는데, 단 한 번만 호출되며 다시 호출 할 수 없는 함수이다. 이유는 그룹 연산자 (...) 내의 기명 함수는 함수 선언문이 아니라 함수 리터럴로 평가되어 함수 이름은 함수 몸체에서만 참조할 수 있는 식별자이므로 즉시 실행 함수를 다시 호출 할 수는 없다.

(function run() {
	console.log('🌞');
})();

// 🌞
run(); // ReferenceError: run is not defined
profile
不怕慢, 只怕站

0개의 댓글