JavaScript에 대하여 - 함수

유니·2021년 12월 6일
1

함수 호출

함수는 함수를 가리키는 식별자와 한 쌍의 소괄호인 함수 호출 연산자로 호출한다. 이때 소괄호 안의 인수는 0개 이상의 쉼표로 구분한다.

function Name(params, [...params] { return }

Name(args, [...args]);

그리고 함수를 실행시키기 위해서는 함수의 소괄호 안의 인수에 맞게 전달인자값을 넣어 함수의 식별자를 호출해야한다.

이때 위에 인자를 받는 변수를 매개변수(parameter) 그리고 매개변수에 전달하는 값을 전달인자(argument)라고 한다.

return은 값을 반환시켜주는 반환문이다. 그렇기에 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나가기 때문에 return이후의 반복 혹은 return이후의 문(statement)는 실행되지않고 무시된다.

또한 return에 대한 표현식을 지정하지않고 return;하면 undefined가 반환된다.

return은 세미콜론 자동 삽입 기능이 추기되어있기대문에 return후 표현식을 줄바꿈을 통해 지정할 경우 의도치않게 undefined가 출력되는 현상이 발생 될 수 있다.

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

add(1,2);
// 3

만약 매개변수보다 적게 인자를 할당하면 할당되지않은값은 undefined값이 지정된다. 만약 위의 함수 add에 add(1)만 할당할 경우 1+undefined가 되기때문에 NaN 값이 출력된다.

매개변수보다 더 많이 인자를 할당하면 순서에 맞춰 할당되고 이후의 값들은 무시된다. add(1,2,3,4,5)하더라도 결국 값은 3이 나온다.

함수는 스코프에 의해 함수 몸체 내부에서만 참조할 수 있고, 함수 몸체 외부에서는 참조할 수 없다. 이말은 즉슨 매개변수의 스코프는 함수내부로 한정된다.

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

참조에 의한 전달은 객체(Object)를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달되는것을 말한다. 이는 두개의 변수식별자들이 하나의 객체를 공유한다는 뜻이 된다. 이러면 무슨일이 발생하는지 아래의 예시를 통해 살펴보겠다.

function changeValue(num, obj){
  num += 100;
  obj.name = 'Min';
}

let num = 100;
let person = { name : 'Kim' };

changeValue(100, person);
console.log(num); // 100
console.log(person); // {name: 'Min'}

위의 예시를 보면 함수 changeValue를 선언해주고 매개변수 num과 obj를 지정하여줬다.

그리고 num의 값에는 100을 더해줬고 obj는 객체로써 obj의 name에 접근하여 min이라는 값을 할당하여줬다. 이제 숫자 num과 객체 person을 선언해주고 changeValue에 값을 대입하였다.

이후 값의 변화를 살펴보기 위해 console.log로 각각 호출하여보았는데 놀랍게도 숫자 num의 값은 100을 더했음에도 불구하고 값이 그대로이고, person의 key인 name의 value값이 Kim에서 Min으로 변경된걸 볼 수 있다.

이러한 현상이 나타나는 이유가 객체가 참조에 의한 전달을 하기때문이다.
숫자의 경우 원시값으로써 변하지않는값이기에 직접 변경할 수 없기 때문에(값에 의한 전달 : 원시값을 갖는 변수를 할당하면 할당받는변수에는 할당되는 변수의 원시값이 복사되어 전달된다. 이때 각각의 변수는 서로다른 메모리 공간에 저장된 별개의 값이다.) 값이 바뀌지 않은것을 볼 수 있다.

하지만. person의 경우 객체로써 참조에 의한 전달을 하기 때문에 person의 객체값 name:'kim' 이 담긴 메모리 주소를 공유 함으로써 함수안에서 name의 value값인 kim을 직접적으로 건들게되면 person의 name의 value값인 kim역시 변하게된다.

이를 방지하기위해 방어적 복사(원본 객체를 완전히 복제), 깊은 복사(새로운 객체를 생성하고 재할당하여 교체)와 같은 방법을 통하여 값이 변경되는 것을 막기도 한다.

다양한 함수의 형태

즉시 실행 함수(IIFE)

즉시 실행 함수는 함수를 정의함과 동시에 즉시 실행하는 함수이다. 즉시 실행 함수의 특징으로는 단 한번 호출되며 다시 호출할 수 없다.

(function (){
  var a= 3;
  var b= 5;
  return a*b;
}());
//15 위와 같이 함수의 이름을 지정해주지않는것을 익명즉시실행함수라고함.

(function add() {
  var a= 3;
  var b= 5;
  return a+b;
}()); // 8 위와같이 add를 붙여 이름을 지정해주는것을 기명즉시실행함수라고한다.
add(3,5) // referenceError: add is not defined 즉시실행함수는 단한번만 호출되고 그 이후 다시 호출할수없기에 add가 defined되지않았다고 참조에러가난다.

즉시실행함수는 위의 예시와 같이 반드시 ()로 감싸줘야한다. 감싸주지않을 경우 즉시실행함수로 이해하지 못하여 함수선언문의 형식에 맞지않다고 에러가 발생한다.

즉시실행함수 역시 값을 반환하여 쓸 수 있다.

var value = (function add() {
  var a= 3;
  var b= 5;
  return a+b;
}());
value; // 8

재귀함수

재귀함수는 자기자신을 호출하는 재귀호출을 이용한 함수이다.

대표적인 예로 팩토리얼이 있다.

function factorial(i){
  if (i <= 1) return 1; //팩토리얼의 특성상 이때 탈출해야한다.
  return i * factorial(i-1);
}
console.log(factorial(5)); // 120

만약 if문과 같은 탈출 조건을 안만들어주면 재귀함수는 무한하게 자신을 호출하기때문에 반.드.시. 탈출 조건을 만들어 탈출해주어야한다.

중첩함수

중첩함수는 내부함수라고도 하는데 쉽게말하면 함수안의 함수이다.
그래서 함수의 스코프 특성상 중첩함수를 호출하기위해선 외부함수를 통해야만 호출할 수 있다. 이는 스코프와 클로저라는 개념이 매우 깊은 관련이 있다.

function outer(){
  var x= 1;
  function inner() {
    var y= 2;
    return x+y;
  }
  return inner();
}
outer(); // 3

콜백함수

콜백함수는 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수이다. 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 고차함수라고한다.

function repeat(x, y){
  for (let i = 0; i < x; i++){
    y(i);
  }
}

let logAll = function(i) {
  console.log(i);
};
repeat(5, logAll);

위의 예제를 보면 repeat라는 for문으로 반복하는 함수가 있고 logAll이라는 함수가 있다. 그리고 repeat의 전달인자로써 5와 logAll을 할당한걸 볼수가있는데 이때 logAll은 전달인자로써 repeat의 매개변수 y에 들어가 repeat의 내부로 전달되엇다. 이 때 logAll은 콜백함수라고 볼 수 있다. logAll은 i값을 할당받아 console.log를 통하여 i값을 출력하는데 이 함수가 repeat에 들어가게되어

function repeat(x,y){
  for (let i = 0; i < x; i++){
    console.log(i);
  }
}

와 같은 형식으로 출력되어 결과값이 0 1 2 3 4 로 출력된다.

고차함수의 경우 이보다 더 복잡한대 이는 나중에 자세히 살펴볼 예정이다.

순수 함수와 비 순수 함수

외부 상태에 의존하지 않고 변경하지도 않는, 즉 부수 효과가 없는 함수를 순수함수라 한다. 외부상태에 의해 변경되거나 외부에 의존하는, 즉 부수효과가 있는 함수를 비 순수 함수라한다.

let count = 0;
function value(x){
  return ++x;
}
value(count); // 1
value(count); // 1
value(count); // 1
//순수함수 value는 언제나 어떤값이 들어와도 동일한 값을 반환한다.
//몇번이다 value(count)를 하여도 값은 언제나 1이다.
var count = 0;
function value(){
  return ++count;
}

value();//1
value();//2
value();//3
//비 순수 함수 value는 값을 받을때마다 반환값이 계속 변하는 모습을 볼 수 있다.
profile
Prospective Junior Front-end Developer

0개의 댓글