JavaScript Function(함수)

황인용·2019년 12월 10일
0

JavaScript

목록 보기
3/4

Function(함수)

함수(Function)이란 어떤 작업을 수행하기 위해 필요한 문(Statement)들의 집합을 정의한 코드블록이다.

function add() {
   let sum = 3 + 3;
   return sum;
}

함수는 이름과 매개변수를 갖으며 필요한 때에 호출하여 코드 블록에 담긴 문들을 일괄적으로 실행할 수 있다.

  • JavaScript Function Syntax
    - function 키워드로 시작
    • '함수이름'을 지정
    • 함수를 알리는 소괄호('(': parentheses)를 열고 닫고
    • 실행할 코드를 작성. 함수의 body
    • return(반환)할 것이 있다면 작성
    • 중괄호('}' : curly bracket )으로 닫어줌

함수 호출

함수의 이름에 괄호 '( )'를 붙어주면 된다

▶ 소스

function add() {
   let sum = 3 + 3;

   return sum;
}

add();

▶ 결과


함수를 호출하면, 그제서야 add()함수를 실행하여 '3 + 3'인 '6'을 변수에 저장하고 'sum'으로 반환한다

  • 함수를 별도의 변수로 저장 및 호출도 가능하다
    ▶ 소스
function checkCorrect() {
  let hi = "안녕하세요";
  
  return hi;
}
console.log(checkCorrect());

▶ 결과

함수의 Parameter(매개변수) | Argument(인자)

▶ Parameter(매개변수) : 함수를 정의하는 코드에서 괄호안에 정의하고 있는 변수

▶ Agrument(인자) : 함수를 호출하는 곳에서 함수에 전달하는 값

function add(x,y) { // add라는 명의 함수, x, y의 parameter
       var total = x + y;
       retrun total; 
}

console.log(10, 20) // argument(인자) 10, 20

함수 선언식(Function Declarations)

일반적으로 프로그래밍 언어에서 함수 선언과 비슷한 형식

// 문법
function 함수명() {
  구현 로직
}
// 예시
function funcDeclarations() {
  return 'A function declaration';
}
funcDeclarations(); // 'A function declaration'

▶ 소스예제

function square(number) {
  return number * number;
}

square();

▶ 결과

함수 표현식(Function Expression)

함수의 일급객체 특성을 이용하여 함수 리터널 방식으로 함수를 정의하고 변수에 할당할 수 있는데 이러한 방식을 함수 표현식(Function expression)이라 한다.

// 문법
var 함수명 = function () {
  구현 로직
}
// 예시
var funcExpression = function () {
    return 'A function expression';
}
funcExpression(); // 'A function expression'

▶ 소스예제

var square = function(number) { return number * number };

square(3);

▶ 결과

화살표 함수 (Arrow Function)

화살표 함수 표현(arrow function expression)은 this, arguments, super 또는 new.taget을 바인딩 하지 않는다.

화살표 함수는 function 키워드 대신 화살표(=>)를 사용하여 간략한 방법으로 함수를 선언한다.

'return'선언없이 반환이 가능하다.

▶ ES 5 소스

//ES_1
var pow = function (x) { return x * x; };
console.log(pow(10)); // 100

//ES_2
var arr = [1, 2, 3];
var pow = arr.map(function (x) { // x는 요소값
  return x * x;
});

▶ ES 6 소스

//ES6_1
const pow = x => x * x;
console.log(pow(10)); // 100

//ES_2
const arr = [1, 2, 3];
const pow = arr.map(x => x * x);

console.log(pow); // [ 1, 4, 9 ]

호이스팅(Hoisting)

함수안에 있는 선언들을 먼저 모두 끌어올려서 해당 *함수유효범위의 최상단에 선언하는 것을 말함

자바스크립트는 Parser가 함수 실행 전 해당 함수를 전체적으로 한번 흝는다.

함수 안에 존재하는 변수/함수 선언에 대한 정보를 메모리에 저장하고 기억해 두었다가 호출했을 시 실행시킨다.

*함수유효범위 : 함수 블록 { } 을 말함

즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어 올리는 것

실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리한다

실제 메모리에서는 변화가 없다

▶ 호이스팅 대상

var 변수 선언와 함수 선언문에서만 호이스팅이 일어난다

  • var변수/함수의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다

  • let/const 변수 선언과 함수 표현식(function expression)에서는 호이스팅이 발생하지 않는다.

▶ 소스예제#1 var변수 먼저 호출 시;

my name;
var myname; // [Hoisting] "선언"

▶ 소스예제#1 결과

▶ 소스예제#2 let 변수 먼저 호출 시;

myname = "HEEE"; // "할당"
let myname2 = "HEEE2"; // [Hoisting] 발생 X

▶ 소스예제#2 결과

▶ 소스예제#3 함수선언식에서 함수 먼저 호출 시
;

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

▶ 소스예제#3 결과

▶ 소스예제#4 함수 표현식에서 함수 먼저 호출 시;

foo();
var foo = function() {
    console.log('hello');
};

▶ 소스예제#4 결과 : Syntax Error

▶ 소스예제#5 함수 선언식에서 함수 내 호출;

function printName(firstname) { // 함수선언문 
    var result = inner(); // "선언 및 할당"
    console.log(typeof inner); // > "function"
    console.log("name is " + result); // > "name is inner value"

    function inner() { // 함수선언문 
        return "inner value";
    }
}

printName(); // 함수 호출 
//////////////////////////////////////////////
function printName(firstname) { 
    var result; // [Hoisting] var 변수 "선언"

    function inner() { // [Hoisting] 함수선언문
        return "inner value";
    }

    result = inner(); // "할당"
    console.log(typeof inner); // > "function"
    console.log("name is " + result); // > "name is inner value"
}

printName(); 

▶ 소스예제#5 결과

▶ 소스예제#6 함수표현식의 선언이 호출보다 위에 있는 경우;

function printName(firstname) { // 함수선언문
     var inner = function() { // 함수표현식 
         return "inner value";
     }
        
     var result = inner(); // 함수 "호출"
     console.log("name is " + result);
 }

 printName(); // > "name is inner value"
/////////////////////////////////////////////
 function printName(firstname) { 
     var inner; // [Hoisting] 함수표현식의 변수값 "선언"
     var result; // [Hoisting] var 변수값 "선언"

     inner = function() { // 함수표현식 "할당"
         return "inner value";
     }
        
     result = inner(); // 함수 "호출"
     console.log("name is " + result);
 }

 printName(); // > "name is inner value"

▶ 소스예제#6 결과

▶ 소스예제##7 함수표현식의 선언이 호출보다 아래에 있는 경우(var변수에 할당);

/* 오류 */
 function printName(firstname) { // 함수선언문
     console.log(inner); // > "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
     var result = inner(); // ERROR!!
     console.log("name is " + result);

     var inner = function() { // 함수표현식 
         return "inner value";
     }
 }
 printName(); // > TypeError: inner is not a function
/////////////////////////////////////////////
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
 /* 오류 */
 function printName(firstname) { 
     var inner; // [Hoisting] 함수표현식의 변수값 "선언"

     console.log(inner); // > "undefined"
     var result = inner(); // ERROR!!
     console.log("name is " + result);

     inner = function() { 
         return "inner value";
     }
 }
 printName(); // > TypeError: inner is not a function

▶ 소스예제#7 결과 : TypeError

▶ 소스예제#8 : 함수 표현식의 선언이 호출보다 아래에 있는 경우 (let/const 변수에 할당);

function printName(firstname) { // 함수선언문
     console.log(inner); // ERROR!!
     let result = inner();  
     console.log("name is " + result);

     let inner = function() { // 함수표현식 
         return "inner value";
     }
 }
 printName(); // > ReferenceError: inner is not defined

▶ 소스예제#8 결과 : ReferenceError

▶ 호이스팅 우선순위

같은 이름의 var변수 선언과 함수 선언에서의 호이스팅

  • 변수 선언이 함수 선언보다 위로 끌어올려진다

▶ 소스예제#1

var myName = "hi";

  function myName() {
      console.log("yuddomack");
  }
  function yourName() {
      console.log("everyone");
  }

  var yourName = "bye";

  console.log(typeof myName);
  console.log(typeof yourName);
/** --- JS Parser 내부의 호이스팅(Hoisting)의 결과 --- */
  // 1. [Hoisting] 변수값 선언 
  var myName; 
  var yourName; 

  // 2. [Hoisting] 함수선언문
  function myName() {
      console.log("yuddomack");
  }
  function yourName() {
      console.log("everyone");
  }

  // 3. 변수값 할당
  myName = "hi";
  yourName = "bye";

  console.log(typeof myName); // > "string"
  console.log(typeof yourName); // > "string"

▶ 결과

▶ 소스예제#2: 값이 할당되지 않은 변수와 값이 할당되어 있는 변수에서의 호이스팅

var myName = "Heee"; // 값 할당 
  var yourName; // 값 할당 X

  function myName() { // 같은 이름의 함수 선언
      console.log("myName Function");
  }
  function yourName() { // 같은 이름의 함수 선언
      console.log("yourName Function");
  }

  console.log(typeof myName); // > "string"
  console.log(typeof yourName); // > "function"

▶ 소스예제#2 결과:

  • 값이 할당되어 있지 않은 변수는 함수선언문이 변수를 덮어쓴다

  • 값이 할당되어 있는 변수의 경우, 변수가 함수선언문을 덮어쓴다

클로저(Closure)

클로저(closure)는 내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킴

부함수가 외부 함수 안에서 정의된 모든 변수와 함수들을 완전하게 접근 할 수 있도록 승인(그리고 외부함수가 접근할수 있는 모든 다른 변수와 함수들까지) 그러나 외부 함수는 내부 함수 안에서 정의된 변수와 함수들에 접근 할 수 없음

▶ 소스예제#1 : 내부함수

function outter(){
    function inner(){
        var title = 'coding everybody'; 
        console.log(title);
    }
    inner();
}
outter();

▶ 소스예제#1 결과

▶ 소스예제#2

function outter(){
    var title = 'coding everybody';  
    function inner(){        
        console.log(title);
    }
    inner();
}
outter();

▶ 소스예제#2 결과

  • outter(); 함수내 inner(); 함수가 정의되어 있다. 함수inner();를 내부 함수라한다

  • inner(); 함수에서 title을 호출했을 때, 외부함수인 outter();함수의 지역변수에 접근할 수 있음을 보여준다.

    ▶ 소스예제#3

    function outter(){
       var title = 'coding everybody';  
       return function(){        
           console.log(title);
       }
    }
    inner = outter();
    inner();

▶ 소스예제#3 결과

![image.png](https://velog.velcdn.com/post-images%2Finyong_pang%2F6f846a90-1b64-11ea-a08c-f18e394da52d%2Fimage.png)
- 변수 inner는 outter();함수를 호출하고 있다.

- inner에는 변수가 없이 호출을 하는데, 지역변수가 소멸되는 것이 아니라 외부함수의 지역변수인 var title를 사용하여 내부함수를 호출하고 있다.

- 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는다

▶ 소스예제#4 : 객체의 메소드에서 클로저
 ```javascript
function factory_movie(title){
    return {
        get_title : function (){
            return title;
        },
        set_title : function(_title){
            title = _title
        }
    }
}
ghost = factory_movie('Ghost in the shell');
matrix = factory_movie('Matrix');
 
console.log(ghost)
console.log(matrix)
console.log(ghost.get_title());
console.log(matrix.get_title());
 
ghost.set_title('공각기동대'); 

console.log(ghost.get_title());
console.log(matrix.get_title());

▶ 소스예제#4 결과

  • factory_movie();함수는 객체를 반환한다. 그 객체는 메소드로 get_title();함수와 set_title();함수를 가지고 있다. 이 메소드들은 외부함수인 factory_movie(); 함수에서 인자값을 전달받는다

  • ghost.set_title('공각기동대'); 에 의해 set_title은 외부함수 factory_movie의 지역변수 title의 값을 '공각기동대'로 변경하였다. 즉, ghost.get_title();의 값이 '공각기동대'로 변경된다는 것은 set_title();함수와 get_title();함수가 title의 값을 공유하고 있다는 의미

  • 외부함수가 실행될 때마다 새로운 지역변수를 포함하는 클로저가 생성되기 때문에 ghost와 matrix는 서로 완전히 독립된 객체이다

  • factory_movie();의 지역변수 title은 2행에 선언된 객체의 메소드에서만 접근할 수 있는 값

  • Javascript는 기본적으로 private한 속성을 지원하지 않는데, 클로저의 이러한 특성으로 private한 속성을 사용할 수 있게 된다.

▶ 소스예제#5 : 클로저응용

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}
for(var index in arr) {
    console.log(arr[index]());
}

▶ 소스예제#5 결과


▶ 소스예제#5 수정

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(id) {
        return function(){
            return id;
        }
    }(i);
}
for(var index in arr) {
    console.log(arr[index]());
}

▶ 소스예제#5 수정 결과

  • 첫번째 for문안에서 arr[i]함수가 내부적으로 인자를 전달하기 위해 id라는 매개변수를 지정한다

  • 지정된 id매개변수가 지역변수 역할을 하여, 가장안에 있는 내부함수가 외부함수 지역변수에 retrun하고 retrun된 값으로 두번째 for문을 통해 0 ~ 4까지 출력함

Assignment

함수 작성에 익숙해지셨나요?

아래의 설명을 듣고 함수를 작성해주세요.

함수 이름은 checkYear입니다.

올해 년도를 return합니다.

년도를 작성할 때는 ""(쌍따옴표)없이 숫자만 4자리 써주세요

▶ 소스

function checkYear() {
  const year = 2019;
  
  return year;
}
console.log(checkYear());

▶ 결과

profile
dev_pang의 pang.log

0개의 댓글