프로그래밍 언어/JavaScript

[JavaScript]function

claire 2022. 1. 13. 16:56

절차적인 언어에서는 함수가 프로그램에서 굉장히 중요한 기능을 담당한다. 

그런데 자바스크립트에는 class가 추가되어서 object oriented programming language가 아닌가??!!!!!? No.

이 클래스도 자바의 class처럼 pure한 object orient가 아니고 프로토타입을 베이스로 한 가짜의 object oriented이다. 

따라서 JavaScript도 절차 지향 언어 중 하나로 볼 수 있다. function이 중요한 역할을 한다. 

 

function declaration

function을 sub-program이라고도 한다. input을 받아 처리 후 output을 리턴하는 것이다. 

function은 한가지 일을 수행해야하고 동사형태로, command형태로 이름을 지정해야한다. 

함수 이름을 짓기가 어렵다면 함수 내에서 너무 많은 일을 하려고 하는 것은 아닌지 의심해봐야한다. 

js에서 function은 object의 일종이다. 따라서 변수에 할당이 가능하고, 인자로 전달이 되고 함수를 리턴할 수도 있다. 

 

js에는 타입이 없어서 parameter만 보면 뭘 전달해야하는지 알 수 없다. 타입이 중요한 경우에는 난해할 수 있다. 해당 문제점은 타입스크립트로 보완할 수 있다. 규모있는 프로젝트를 하거나 협업할때는 타입스크립트를 쓰는 것이 좋다.

 

1. parameters 

primitive parameters: passed by value

object parameters: passed by reference

function changeName(obj) {
  obj.name = 'coder';
}
const ellie = { name: 'ellie' };
changeName(ellie);
console.log(ellie);

함수 내에서 오브젝트 값을 변경하게 되면 그대로 메모리에 반영이 된다.

 

2. Default parameters

// 3. Default parameters (added in ES6)
function showMessage(message, from = 'unknown') {
  console.log(`${message} by ${from}`);
}
showMessage('Hi!');

인자의 초기값을 설정할 수 있다. 

 

3. Rest parameters

function printAll(...args) {   //...을 쓰면 배열형태로 전달되게 된다.  
  for (let i = 0; i < args.length; i++) {
    console.log(args[i]);
  }

  for (const arg of args) {   //for of로 반복문 가능. 
    console.log(arg);
  }

  args.forEach((arg) => console.log(arg));  
}
printAll('dream', 'coding', 'ellie');  //3개의 값을 전달.

printAll. 을 하면 함수가 object로 전환이 되기 때문에 printAll의 속성값을 확인해볼 수 있다. 

 

4. Local scope

밖에서는 안이 보이지 않고 안에서만 밖이 보인다. 

let globalMessage = 'global'; // global variable
function printMessage() {
  let message = 'hello';
  console.log(message); // local variable
  console.log(globalMessage);
  function printAnother() {
    console.log(message);   //부모 영역 변수 접근 가능
    let childMessage = 'hello';
  }
  // console.log(childMessage); //error  자식 영역 변수에는 접근할 수 없다. 
}
printMessage();

5. Return

return값이 없는 함수는 return undefined가 들어가 있는 것과 똑같다. 이것은 생략이 가능하다. 

 

6. Early return, Early exit

// bad - 블럭 안에서 로직을 많이 작성하는 것은 좋지 않다. 가독성이 떨어짐. 
function upgradeUser(user) {
  if (user.point > 10) {
    // long upgrade logic...
  }
}

// good - 조건이 맞지 않는 경우를 빨리 리턴하고 맞는 경우 그 다음 로직을 진행하는 것이 좋다. 
function upgradeUser(user) {
  if (user.point <= 10) {
    return;
  }
  // long upgrade logic...
}

 

function expression

 

function expression덕에 first-class function 이 가능하다. 

const print = function () {   // anonymous function- 함수에 이름이 없이 필요한 부분만 작성해서 변수에 할당
  console.log('print');
};
print();
const printAgain = print;     //변수에 함수 할당
printAgain();
const sumAgain = sum;		//웨에서 작성된 sun함수도 변수에 할당 가능하다. 인자도 전달 가능
console.log(sumAgain(1, 3));

function declaration과 function expression의 차이점!!

function declaration은 hoisting이 가능하다. 반면에 function expresion은 할당된 다음부터 호출이 가능하다.

함수가 선언되기 이전에 호출되어도 호출이 가능하다. 그 이유는 자바스크립트 엔진이 선언을 제일 위로 올려주기 때문이다.  

sum(1,2);   //이것은 가능하지만
function sum(a, b) {
  return a + b;
}


print(); //이것은 안된다는 말이다. 
const print = function () {
  // anonymous function
  console.log('print');
};

 

callback

매개변수로 함수를 전달하여 해당하는 상황에 함수를 호출하는 것을 callback function이라 한다.  

function randomQuiz(answer, printYes, printNo) {
  if (answer === 'love you') {
    printYes();
  } else {
    printNo();
  }
}
// anonymous function
const printYes = function () {
  console.log('yes!');
};

// named function
// 디버깅시 debugger의 stack traces에 이름이 나오게 하도록 이름을 쓰는 것이다.
//또는 자신 스스로를 본인 함수 안에서 호출 하기 위해 사용. 이건 정말 별로다. 필요할때만 사용해라. 
// recursions
const printNo = function print() {
  console.log('no!');
  
};
randomQuiz('wrong', printYes, printNo);
randomQuiz('love you', printYes, printNo);

 

Arrow function 

이것은 항상 anonymous function이다. 

const simplePrint = () => console.log('simplePrint!');
const add = (a, b) => a + b;
const simpleMultiply = (a, b) => {
  // 블럭을 쓰게 되면 리턴으로 값을 전달해야한다. 
  return a * b;
};

 

IIFE : Immediately Invoked Function Expression

(function hello() {
  console.log('IIFE');
})();

선언함과 동시에 호출을 하는 방법. 최근에는 잘 쓰지 않는다.