12. 함수

브리·2022년 6월 12일
0

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

함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출 가능하지만,
함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출 할 수 없다.
-> 생성시점이 다르기 때문임!

1) 함수 선언문 : 런타임 이전에 함수 객체가 생성되고 함수 이름과 동일한 이름으로 식별자를 생성하고 식별자에 할당까지 완료함. 함수 호이스팅이 일어나는 것이다.

  • var 호이스팅이랑 함수 호이스팅의 차이점 : var, 함수 모두 런타임 이전에 엔진에서 먼저 실행되는 것은 동일하지만 var은 undefined 로 초기화 되고, 함수는 함수 객체로 초기화된다. 그래서 함수 선언문은 함수 호이스팅에 의해 호출이 가능하다!

2) 함수 표현식 : 실행단계에서 함수 객체 생성

  • 함수 표현식은 변수에 할당되는 값이 함수 리터럴(문)이다. 변수 선언은 런타임 이전에 실행되어서 undefined 로 초기화되기 때문에 함수 호이스티 없이 변수 호이스팅만 발생한다.

함수 호이스팅은 함수를 호출하기 전에 함수를 선언해야한다는 규칙을 무시하기 때문에 이왕이면 함수 표현식을 쓰자링

Function 생성자

var add = new Function('x','y','return x+y');
console.log(add(2,5));

근데 이 방법은 클로저가 생성되지 않기 때문에 권장하지 않음

화살표 함수(ES6)

const add = (x, y) => x + y;
console.log(add(2, 5)); // 7
  1. this 바인딩 방식이 다름
  2. 프로토타입 프로퍼티가 없음
  3. arguments 객체를 생성하지 않음

함수 호출

함수는 함수를 가리키는 식별자와 소괄호() 인 함수 호출 연산자로 호출함.
함수를 호출하면 실행 흐름을 중단하고, 호출된 함수로 실행 흐름을 옮긴다. 매개변수에 인수가 순서대로 할당되고 함수 몸체의 문들이 실행된다.

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

add(2, 5);

// add 함수의 매개변수 x, y는 함수 몸체 내부에서만 참조할 수 있다.
console.log(x, y); // ReferenceError: x is not defined

당연하지만 함수 매개변수의 스코프는 함수 내부임!
함수 매개변수와 인수의 개수는 일치하지 않아도 된다. 인수가 부족하면 할당되지 않는 매개변수는 undefined 고 넘치면 무시

함수는 가급적 작게 만들어야하고 하나의 기능만 하게 해야한다. 고로 이상적인 매개변수의 개수는 3개 이하이다.

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

원시값은 값에 의한 전달, 객체는 참조에 의한 전달임. 그래서 값을 할당하고 할당한 새로운 값을 변경했을 때 기존 원시값은 변화가 없고 기존 객체값은 변화한다.

// 원시값과 오브젝트를 매개변수로 전달 받음
function changeVal(primitive, obj){
  primitive += 100;
  obj.name = 'Kim';
}

//외부
var num=100;
var person={name : 'Lee'};

console.log(num); //100
console.log(person); //{name: "lee"}

//함수 실행
changeVal(num, person);
console.log(num); //100 - 그대로
console.log(person); //{name: "Lee"}

위에서 볼 수 있듯 원시 값은 복사되기 때문에 함수가 실행되어도 외부 값이 변하지 않지만 객체는 참조값이 복사되고 변경 가능한 값이기 때문에 함수가 실행되면 값이 변경된다.

이렇게 되면 코드 변경의 추적이 어려워짐

해결방법

  1. 옵저버 패턴을 통해 변경사항을 통지하기
  2. 불변객체 만들기 - 변경이 필요한 경우는 깊은복사로 새로운 객체 생성하고 재할당하기

순수함수(외부상태에 의존하지 않는 함수)를 만들어서 부수 효과 억제하기가 중요함

즉시실행 함수

함수에 ()를 씌우면 즉시실행되고 익명함수를 주로 쓴다. 한 번 쓰고 사라짐.

재귀함수

반복처리를 위해 사용함.

function factorial(n){
  if(n<=1) return 1; //탈출
  return n*factorial(n-1);
}

factorial(5);
//호출하면 return 5*4*3*2*1

재귀함수는 본인을 무한으로 호출하므로 탈출조건을 꼭 넣어줘야한다.
또한 모든 재귀함수는 반복문으로 만들 수 있으니 재귀함수를 꼭 써야할 때만 쓰자.

중첩함수

함수 내부에 정의된 함수

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

중첩함수는 외부 함수 내부에서만 호출 가능함. 스코프가 외부 함수 내에서만 한정되어 있어서임. 중첩함수는 또한 클로저와 관련이 있는데, 이건 다음장에서 더 자세히 알아보도록 하자.

콜백함수

함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수,
매개변수를 통해 함수의 외부에서 콜백함수를 전달받은 함수를 고차함수 (HOF)
repeat 함수가 고차함수고, 들어가는 logAll 이 콜백함수임

function repeat(n, f) {
  for (var i = 0; i < n; i++) {
    f(i); // i를 전달하면서 f를 호출
  }
}

var logAll = function (i) {
  console.log(i);
};

repeat(5, logAll); // 0 1 2 3 4

//보통 익명함수 리터럴로 정의하면서 곧바로 고차함수에 전달하는 것이 일반적임. 이런식으로!
repeat(5, (i)=>{
	if(i%2) console.log(i);
})

순수함수와 비순수함수

📌 순수함수 : 외부 상태에 의존하지 않고 변경하지도 않는 부수효과가 없는 함수, 동일한 인수가 전달되면 언제나 동일한 값을 반환함, 전달된 인수에만 의존해서 반환값을 만든다.
📌 비순수함수 : 외부 상태에 의존하거나 부수효과 있는 함수


악 내용도 너무 많고 어렵다잇 ㅜ.ㅜ

profile
무럭무럭

0개의 댓글