[Deep Dive][12장] 함수

hyeongjundev·2023년 3월 4일
0

deepdive

목록 보기
5/7

함수

함수란

  • 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위를 정의
//함수정의시작
function add(x, y) {  //add함수이름 x,y 매게변수
    return x + y;  //반환값 
}

//함수정의끝
add(2, 5); //함수호출
add(4, 5); //함수재사용

함수 사용 이유

  • 코드의 재사용
  • 코드의 가독성 향상
  • 코드의 신뢰성 높임

함수 리터럴

  • 정의: 함수를 생성하는 표기법
    • 리터럴 복습: 사람이 이해할 수 있게 기호를 사용해 값을 생성하는 표기방식
//변수에 하수 리터럴을 할당
var f = function add(x, y) {
    return x + y;
}
  • 함수 리터럴 구성요소
    • 함수이름
      • 식별자
      • 기명함수와 익명함수
    • 매개변수
    • 함수몸체
      • 함수가 실행되었을 때 일괄적으로 실행될 문들 정의한 코드 블록
      • 함수 호출에 의해 실행
  • 일반 객체는 호출 할 수 없지만 함수는 호출 할 수 있다
  • 함수도 객체(18장에서 자세히)

함수 정의(총4가지)

  1. 함수 선언문
function add(x, y) {
    return x + y;
}
  • 문(복습)
    • 프로그램을 구성하는 기본 단위이자 최소 실행단위
    • 크롬 브라우저에 표현식이 아닌 문을 실행하면 언제나 undefined 출력, 완료값 이라고함
    var x; //변수선언문
    x = 5; //할당문->undefined 안뜸
    function foo(){}; //함수선언문
    if(x>1) {console.log(x)}; //조건문
    for(var i =0; i<2; i++){console.log(i);} //반복문

-표현석이 아닌 문은 변수에 할당 할 수 없다?

//함수 선언문은 표현식이 아닌 문이므로 변수에 할당 할 수 없다
//하지만 함수 선언문이 변수에 할당되는 것처럼 보인다
//함수 리터럴의 중의적 표현에 의해 표현식으로 판단됨
var add = function add(x,y){
    return x+y;
}
add(2,5)//7
  • {} 중의적 의미
    • {}이 단독으로 존재하면 블록문
    • {}이 피연산자로 사용되면 즉 우변에 있으면 객체 리터럴로 해석
  • 함수 리터럴의 중의적 의미
    • 단독으로 사용할 경우 함수선언문으로 해석
    • 변수에 할당하거나 피연사자로 사용하면 함수리터럴 표현식으로 판단
//함수 리터럴 단독이면 선언문
function foo(){console.log('foo');}
foo(); //foo
(function bar(){console.log('bar');});
bar(); //referenceError: bar is not defined
  • ()내에 있는 함수는 선언문으로 안되고 함수리터럴 표현식으로 해석
  • 함수 이름은 함수 몸체내에서만 참조할 수 있는 식별자
    • 외부에서 함수이름을 호출 할 수 없다는 의미, 즉 식별자가 없다
    • 그럼 위에 foo()는 어떻게 호출되었을까? -> 자바스크립트에서 엔진이 암묵적으로 생성한 식별자
var add= function add(x,y){
    return x+y;
}
add(2,5); //할당된 식별자 호출
  • 위 예제는 함수이름을 호출 한 것이 아니라 함수 객체가 가리키는 식별자를 호출
  • 즉 엔진이 암묵적으로 생성한 식별자 add
  • 단 함수 선언문과 함수 표현식이 정확히 동일하게 동작하는건 아님
  1. 함수 표현식
var add = function (x, y) {
    return x + y;
}
  • 표현식(복습)
    • 값으로 평가될 수 있는 문
    • 즉 결과가 있음
var score=100;
score;// 100
10+20
square()
person.getName()
  • 일급객체
    • 변수에 할당
    • 프로퍼티 값
    • 배열의 요소
  • 함수는 일급객체 즉 함수를 값처럼 자유롭게 사용할 수 있다
  • 이러한 정의방식을 함소 표현식
  • 함수 리터럴의 이름은 생략 할 수 있으며 익명함수라 부른다
  • 함수 표현식 대부분이 이름이 생략
var add= function foo(x,y){
    return x+y;
}
undefined
add(2,5); //7
foo(2,5); ///VM636:1 Uncaught ReferenceError: foo is not defined
  • 함수 표현식과 선언문은 동일하게 동작하는것처럼 보이나 아니다
  • 표현식은 표현식인 문이고 함수선언문은 표현식이 아닌문
//함수 참조
console.dir(add); //f add(x,y) 
console.dir(sub); // undefined

//함수 호출
console.log(add(2,5)); // 7
console.log(sub(2,5)); // TypeError: sub is not a function

//함수 선언문
function add(x,y){
    return x+y;
}

//함수 표현식
var sub = function(x,y){
    return x-y;
}
  • 함수 선언문 정의 이전에 사용 가능
  • 함수 표현식 정의 이전에 사용 불가능
  • 선언문과 표현식의 함수생성 시점이 다르다
  • 함수 선언문
    • 런타임 이전 엔진에 의해 먼저 실행, 함수 객체가 먼저 생성
    • 그리고 엔진이 함수 이름과 동일한 식별자 암묵적으로 생성하고 할당
    • 이처럼 함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 것을 함수 호이스팅이람함
  • 함수 호이스팅과 변수 호이스팅 차이
    • 런타임 이전에 엔진에 의해 먼저 실행되어 식별자를 생성하는 건 동일
    • 하지만 var키워드 변수는 undefined로 초기화되고 함수 선언문은 함수객체로 초기화
    • var 키워드 선언 이전에 변수 참조하면 undefined, 함수 선언문은 호이스팅에 의해 호출 가능
    • 함수 표현식의 리터럴도 변수호이스팅이 되면서 undefined할당 이후 런타임에 객체가 할당됨
    • 함수 호이스팅은 함수 호출 전 함수를 선언해야하는 규칙을 무시함으로 표현식 사용할 것을 권장
console.log(k); //undefined
var k=10;
  1. Function 생성자 함수
var add = new Function('x', 'y', 'return x+y');
  • 클로저 생성 불가 등 다른 생성함수와 달라 사용하는걸 추천하지 않는다.
  • 생성자 함수
    • 객체를 생성하는 함수를 뜻함
  1. 화살표 함수(ES6)
var add = (x, y) => x + y;
  • 항상 익명 함수로 정의
  • 기존 함수 선언, 표현문을 대체하는건 아님
  • 내부동작 또한 간략화 되었다
  • 기존 함수와 this 바인딩이 다르고 prototype이 없고 arguments객체를 생성안한다
  • 자세한건 26절에서 나옴

함수 호출

  • 함수를 가리키는 식별자와 한쌍의 소괄호인 함수 호출 연산자로 호출
  • 함수가 호출되면 현재 실행 흐름을 중단하고 호출된 함수로 실행 흐름을 옮김
  • 매개변수와 인수
function add(x,y){ 
    return x+y;
}
//인수1 , 2 가 매개변수 x, y 에 순서대로 할당되고 몸체가 실행
var result = add(1,2)

add(1,2,19);// 초과된 인수는 무시되고 암묵적으로 arguments객체 프로퍼티에 보관
  • 자바스크립트 함수는 매개변수와 인수의 개수가 일치하는지 확인하지 않는다
  • 자바스크립트는 동적 언어로 함수에서 매게변수 타입을 지정 할 수 없다
  • 단축평가를 사용해 매개변수에 기본값 할당(9.4절참고)
function add(a,b,c){
    a=a||0;
    b=b||0;
    c=c||0;
    return a+b+c;   
}
add(1,2,3); //6
add(1,2); //3
add(1); //1
add(); //0
  • 이상적인 함수는 한가지 일만 해야하며 가급적 작게 생성
    ###참조에 의한 전달과 외부 상태의 변경
  • call by value
  • call by reference
function changeVal(primitive, obj){
    primitive+=100;
    obj.name='kim';
}
//외부 상태
var num=100;
var person = {name: 'Lee'};

changeVal(num,person);
console.log(num); //100 값 보존
console.log(person); //{name: 'Kim'} 원시값 훼손
  • 객체 타입 인수는 참조 값이 복사되어 값이 훼손 된다
  • 깊은 복사를 통해 새로운 객체를 생성하고 재할당을 해야지 부수효과를 없앨 수 있다
  • 깊은 복사 참고(https://leonkong.cc/posts/js-deep-copy.html)

즉시 실행 함수

var res=(function(){
    var a=3;
    var b=5;
    return a*b;
}())
console.log(res);//15
res = (function(a,b){
    return a*b;
}(3,5))
console.log(res);//15

0개의 댓글