개발정리

javascript / Chapter4. 함수 1 본문

JS/javascript

javascript / Chapter4. 함수 1

성구님 2017. 1. 31. 23:07
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

00 들어가며

01 함수객체

02 함수리터럴

03 호출

04 인수배열

05 반환

06 예외

07 기본타입에 기능 추가

08 재귀적 호출

 

00 들어가며

  • 함수는 실행 문장들의 집합을 감싼 형태
  • 모듈화의 근간
  • 일반적으로 프로그래밍 기술은 "요구사항의 집합을 함수와 자료구조의 집합으로 반환"하는 것

 

01 함수객체

  • 함수 또한 객체이다.
  • 함수 객체는 Function.prototype에 연결된다. Function.prototype이 가장 근간이 된다. Object.prototype의 proto 또한 Function.prototype이다.
  • 숨겨진 두 속성 문맥(context)와 코드(code)가 있다.
  • 또한 모든 함수 객체는 prototype이라는 속성이 있다. 이 속성값은 함수 자체를 값으로 갖는 constructor라는 속성이 있는 객체이다.
  • 이는 Function.prototype의 숨겨진 연결과는 구분된다.
  • 함수는 변수나 객체, 배열등에 저장된다.
  • 인수로도 사용 가능하다.
  • 반환값으로도 사용 가능하다.
  • 함수는 다른 객체와는 달리 호출이 가능하다.

 

02 함수 리터럴

  • 리터럴 4가지 부분
     + function (필수)
     + 함수명 (선택)
     + 괄로로 둘러 쌓인 매개변수 집합 (필수)
     + 중괄호  (필수)
  • 함수는 다른 함수 내부에서도 정의 가능하다.
  • 내부 함수는 외부함수에 접근 가능. 외부 문맥으로의 연결이 있는데 이를 클로저라 한다.

 

03. 호출

  • 함수를 호출하면 → 현재 함수 실행 잠시 중단→ 호출한 함수로 제어권과 매개변수 전달
  • 이 과정에서 추가로 this와 arguments를 추가로 받게된다.
  • 함수를 호출하는 4가지 방식
    1) 메소드 호출 패턴
       + 함수를 객체의 속성에 저장하는 경우 이 함수를 메소드라 부른다. 
       + 메소드를 호출 할 때, this는 메소드를 포함하고 있는 객체에 바인딩 된다 (this는 객체 그 자체가 된다.)

    메소드 호출패턴
    var myObject = {
        value : 0,
        increment : function (inc) {
            this.value += typeof inc === 'number' ? inc : 1;
        }
    };
      
    myObject.increment();
    console.log(myObject.value); // 1
    myObject.increment(2);
    console.log(myObject.value); // 3



    2) 함수호출 패턴
       + 함수가 객체의 속성이 아닌 경우 함수로서 호출
       + var sum = add(3, 4); → 여기서 this는 전역 객체에 바인딩 된다. 언어 설계 단계의 실수.
       + 해결 대안으로 메소드에서 변수를 정의 후 해당 변수에 this를 할당. 내부 함수는 이 변수를 통해 this에 접근 가능하다.

    함수 호출 패턴
    // 위 메소드 호출 패턴의 myObject 코드가 있다는 가정하에
    function add (num1, num2) {
        return num1 + num2;
    }
      
    myObject.add = function () {
        var that = this;
        var helper = function () {
            this.value = add(that.value, that.value); // value = 3
        };
        helper();
    };
     
    myObject.add();
    console.log(myObject.value); // 6


    3) 생성자 호출 패턴
       + 객체가 자신의 속성들을 다른 객체에 바로 상속할 수 있다.
       + 함수를 new라는 전치연산자와 함께 호출. 호출한 함수는 prototype 속성의 값에 연결되는 (숨겨진) 링크를 갖는 객체가 생성되고 이 객체는 this에 바인딩 된다.
       + new 전치사는 return 문장의 동작을 변경.
       + new는 생성자 역할 ( constructor)
       + 생성자를 new 없이 호출하면 컴파일 시간이나 실행시간에 어떠한 경고도 알 수없다. 
       + 권장하지 않는 호출 패턴 

    생성자 호출 패턴
    var Quo = function (string) {
        this.status = string;
    }
      
    Quo.prototype.get = function () {
        return this.status;
    }
      
    var myQuo = new Quo('good');
      
    console.log(myQuo.get()); // 'good'

     


    4) apply 호출 패턴 
       + 함수는 메소드를 가질 수 있다.
       + apply는 this와 매개변수 배열을 받는다.
       + this는 첫 매개변수로 상위 함수에서 이 메소드의 this값을 선택할 수 있다.

    apply 호출 패턴
    var arr = [3, 4];
    var sum = add.apply(null, arr);
      
    var statusObject = { status : 'ok'};
    var s = Quo.prototype.get.apply(statusObject);
  • 함수를 호출 할 때 매개 변수의 갯수가 달라도 오류는 발생하지 않는다.
  • 매개변수가 받아야되는 수 보다 적은 경우 선언되지 않은 값은 undefined

 

04 인수배열

  • 함수를 호출 할 때 추가적인 매개변수로 arguments라는 배열 사용가능. 모든 인수 접근 가능
  • arguments는 실제 배열이 아니다. 배열 같은 객체.

    apply 호출 패턴
    var sum = function () {
        var i, sum = 0;
        for(i=0 ; i < argunments.length ; i++) {
            sum = sum + arguments[i];
        }
        return sum;
    }
      
    console.log(sum(4, 8, 15, 16, 23, 42)); // 108
      
    // 유용한 패턴이 아니다. 실제 배열이 아니기 때문.
    // 6장에서 이와 유사한 메소드를 배열에 추가하는 것을 살펴볼 예정이다.

 

05 반환

  • 함수호출 → 실행 → 닫는 "}" → 끝 → 함수를 호출한 부분으로 반환
  • return은 함수 실행이 끝에 도달하기전 즉시 반환한다.
  • 항상 값을 반환한다. 반환값이 지정되지 않은 경우 undefined를 반환한다.
  • 함수는 new라는 전치 연산자와 함께 실행하고 반환값이 객체가 아닌 경우 반환값은 this(새로운 객체)

 

06 예외

  • throw문은 함수 실행을 중단한다.
  • throw문은 어떤 예외인지(name), 예외에 대한 설명(message)속성을 가진 객체를 반환해야 한다.

    예외
    var add = function (a,b) {
        if(typeof a !== 'number' || typeof b !== 'number') {
        throw {
                name : 'type error',
        message : 'add needs number'
        };
        }
        return a + b;
    }
      
    var result = add('a', 3);
    //Object {name: "type error", message: "add needs number"}
    //message:"add needs number"
    //name:"type error"

     

     

  • try 블록 내에서 예외 발생시 catch 블록으로 이동

  • 만약 예외 상황에 맞게 대처하고 싶다면 예외의 name 속성을 참고.

 

07 기본타입에 기능 추가

  • 기본타입에 기능 추가
     

    기본타입 1
    // 기능을 추가하기 위해 가장 근간이되는 Function.prototype에 method 추가.
    Function.prototype.method = function (name, func) {
        this.prototype[name] = func;
        return this;
    }
      
    // 숫자형에서 정수만 추출하는 추가 기능
    Number.method('integer'function (){
        return Math[this < 0 ? 'ceil' 'floor'](this); // ceiling 은 실행이 안된다. 없는 메소드?
    });
      
    console.log((-10/3).integer()); //-3
      
    String.method('trim'function (){
        return this.replace(/^\s+|\s+$/g, '');
    });
      
    console.log('"' + "    neat    ".trim() + '"'); // "neat"
      
  • prototype은 public형이다.
  • 그러므로 라이브러리들을 섞어 사용할 때 주의해야 한다.
  • 방어적인 방법은 존재하지 않는 메소드만 추가하는 것.
     

    방어적인 기본타입
    // 메소드가 존재하는지 확인 후 추가. 있다면 추가하지 않는다.
    Function.prototype.method = function (name, func) {
        if(!this.prototype[name]){
            this.prototype[name] = func;
        }  
    }
      

 

08 재귀적 호출

  • 직접 혹은 간접적으로 자신을 호출하는 함수
  • 하노이의 탑 퍼즐 → 전형적인 재귀 문제.
    + 3개의 기둥에 지름이 각기 다른 원반들
    + 정렬된 기둥에서 다른 기둥으로 원반을 옮겨야 한다.
    + 작은 크기 원반 위에는 큰 원반이 못온다.
     

    하노이의탑
    var hanoi = function (disc, src, aux, dst) {
        if(disc > 0){
            hanoi(disc - 1, src, dst, aux);
            console.log('move disc ' + disc + ' from ' + src + ' to ' + dst);
            hanoi(disc - 1, aux, src, dst);
        }
    };
      
    hanoi(3, 'src''aux''dst');
  • 자바스크립트는 꼬리재귀 최적화를 지원하지 않는다.
  • 따라서 매우 깊은 단계의 재귀호출은 스택의 과다사용으로 제대로 실행되지 않을 수 있다. 




참고문헌

1. 더글라스 크락포드, 김명신  자바스크립트 핵심가이드 javascript The good parts』, 한빛미디어

Comments