Hello World

8장 함수 본문

Javascript/Book Study

8장 함수

EnterKey 2012. 8. 29. 18:03
반응형

1. 함수의 정의와 호출

- function 키워드로 시작하며 다음과 같은 항목들이 따라온다.

1. 함수의 이름

2. 함수()안에 0개 혹은 임의 개수의 매개변수 이름을 쉼표로 분리한 목록

3. 중괄호 {} 안에 함수의 몸체를 구성하는 자바스크립트 문장들


- return문에 연결된 표현식이 없다면 함수는 undefined값을 반환한다.

-> 함수에 return 문이 없으면 단순히 함수 몸체를 이루는 문장들을 하나씩 실행한 뒤에

     undefined 값을 호출자에게로 반환한다.


- 일반적으로 매개변수는 실행되는 함수의 몸체 안에서만 유효하며 함수의 밖에서 또는 

   함수가 반환한 후에는 접근할 수 없음을 유의하라.


- 전달인자의 데이터 타입이 중요하다면 typeof 연산자를 사용하여 직접 테스트할 수 있다.

- 함수가 기대하는 개수보다 많은 수의 전달인자를 전달하면 함수는 

   이런 추가분의 전달인자들을 무시한다.


- 함수가 기대하는 개수보다 적은 수의 전달인자를 전달하면 빠뜨린 매개변수에는 

   undefined 값이 할당된다.


1.1 중첩된 함수


 ex) function hypotenuse(a, b) {

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

return Math.sqrt(sqare(a) + square(b) );

}


- 중첩된 함수는 그 함수가 중첩되어 위치하는 함수의 최상위 레벨에서만 정의될 수 있다. 

   즉 if문이나 while 루프의 몸체 같은 문장 블록 안에서는 정의될 수 없다. 

   이러한 제약은 오직 function 문에 의한 함수 정의에만 해당된다.


1.2 함수 리터럴


 비교) function f(x) { return x*x }          // function 문

  var f = function (x) { return x*x } // 함수 리터럴


 - 함수리터럴 문법은 선택적으로 함수 이름을 지정하는 것도 허용한다. 재귀 함수 작성시에 유용

 - 자바스크립트 문장이 아니라 표현식으로 생성된다. 따라서 매우 유연하며, 

    한번만 사용되고 버려지기 때문에 이름 붙이지 않아도 되는 일회용 함수를 정의하는데 적합.


 1.3 함수 이름 붙이기 


  - 너무 간결한 이름보다는 함수를 잘 설명할 수 있는 이름을 사용하라.

  - 함수이름은 일반적으로 동사 혹은 동사로 시작하는 구절이다.



2. 함수 전달 인자


2.1 가변 길이 전달인자 목록: 전달인자 객체

: 자바스크립트 함수는 고정된 개수의 이름 붙은 전달인자들로 정의되지만 

  호출 시점에서는 이 고정된 개수와는 상관없이 임의 개수의 전달인자들을 건네받을 수 있다. 


- Arguemnts 객체 : 배열과 유사한 객체로서 함수에 전달 된 전달인자의 값을 

     전달인자 이름이 아니라 숫자를 사용해 접근하기 위한 방법을 제공 

- arguments : Arguments 객체를 참조하는 특별한 프로퍼티. 배열이 아니라 Arguments객체
           because : arguments.length 프로퍼티에 새로운 값을 할당할 수 있지만,  
                          ECMAScript 에서는 객체가 가진 배열 원소들의 개수를 실제로 변경하는 

  작업을 수행하지는 않는다.


ex) arguments 객체를 사용하여, 

임의 개수의 전달인자를 건네받아서 가장 큰 값의 전달인자를 반환하는 max() 함수 


function max( /* .. */ ) {

var m = Number.NEGATIVE_INFINITY;


for( var i = 0 ; i < arguments.length ; i++ ) {

if ( arguments[i] > m ) m = arguments[i];


return m ;

}


var largest = max(1, 10, 100, 2, 3, 1000, 4, 5, 10000, 6);


3. 데이터로서의 함수

: 함수는 객체 프로퍼티에도 할당될 수 있다.


var o = new Object;

o.square = function(x) { return x*x; } // 함수 리터럴 

y = o.square(16);                            // y에는 256이 저장된다.


4. 메서드로서의 함수

: 객체 프로퍼티에 저장되어 객체를 통해 호출할 수 있는 자바스크립트 함수


5. 생성자 함수

: 객체의 프로퍼티들을 초기화하는 함수. new 연산자와 함께 사용될 의도로 작성


6. 함수 프로퍼티와 메서드

: 함수에 대해 typeof 연산자를 사용하면 "function" 문자열을 반환함,

  함수도 객체이기 때문에 Date나 RegExp 객체처럼 프로퍼티와 메서드가 있음.


6.1
ex) function check(args) {

var actual = args.length;    // 실제로 건네받은 전달인자 개수

var expected = args.callee.length; //함수가 기대하는 전달인자 개수

if ( actual != expected_ { // 두 수치가 일치하지 않으면 예외를 발생시킨다.

throw new Error(Wrong number of arguments : expected: " +

expected + "; actually passed " + actual ) ;

}

}


function f( x, y, z) {

// 메서드가 기대하는 개수의 전달인자를 실제로 전달 받았는지 검사한ㄷ.

// 그렇지 않다면 예외를 발생시킨다.

check(arguments);

// 이제 함수가 해야 할 나머지 일들을 수행한다.

return x + y + z;

}


6.2 prototype 프로퍼티

: 모든 함수에는 미리 정의된 prototype 객체를 가리키는 prototype 프로퍼티가 있다.

  이 prototype 객체는 함수가 new 연산자를 통해 생성자로 사용될 때, 

  새 객체를 정의 하는 과정에서 매우 중요한 역할을 수행한다.


6.3 나만의 함수 프로퍼티 정의하기

: 함수 호출의 경계를 넘어 존재가 유지되는 변수의 사용해야 할 때가 있다. 이때엔 전역변수를 정의하여 네임스페이스를 지저분하게 하는 대신 Function 객체의 프로퍼티를 사용하는 것이 유용할 수 있다. 

 예를 들어 고유한 정수 값을 반환해주는 함수를 작성하려 한다고 가정한다. 이 함수는 절대로 같은 값을 반복하여 반환해서는 안된다. 이를 위해서 함수는 이미 반환한 값들에 대한 정보를 기록하고 있어야 하며 이 정보의 존재는 함수 호출의 경계를 넘어 지속되어야만 한다. 이 정보는 전역 변수에 저장할 수 있으나 한 함수에서만 사용되는 정보를 그렇게 전역으로 정의하는 것은 불필요한 작업이다. 이 경우에는 정보를 Function 객체의 프로퍼티에 저장하는 것이 더 좋다.


ex) 

// '정적' 변수를 생성하고 쵝화 한다.

// 함수 선언은 코드가 실행되기 전에 처리된다. 따라서 다음과 같은 할당 연산을

// 함수 선언 이전에 실제로 수행할 수 있다.

uniqueInteger.counter = 0;


// 여기에 선언된 함수는 호출되 ㄹ때마다 서로 다른 고유한 값을 반환한다. 이 함수는

// 마지막으로 반환한 값에 대한 정보를 기록하기 위하여 '정적' 프로퍼티를 사용한다.

function uniqeInteger() {

// '정적' 변수를 증가시키고 반환한다.

return uniqueInteger.counter++;

}


6.4 apply()와 call() 메서드

: 함수가 마치 다른 어떤 객체의 메서드인 것처럼 호출할 수 있다.


 첫 번째 전달인자는 함수가 소속되어 호출될 객체를 저징하며 이 전달인자는 함수 몸체 안에서 this 키워드의 값이 된다. call() 메서드의 나머지 전달인자들은 함수가 호출될 때 함수의 전달인자로 건네진다. 


ex) f.call(o, 1, 2);

 : 함수 f()에 두 숫자를 전달하고 이 함수를 마치 객체 o의 메서드인 것처럼 호출하려 한다.


 o.m = f;

 o.m(1,2);

 delete o.m;


cf) apply() 메서드는 call() 메서드와 유사하지만 

   함수로 건네 줄 전달인자들을 배열로 지정한다는 점이 다르다.

ex) f.apply(o, [1,2]);


ex) var biggest =  Math.max.apply(null, array_of_numbers);

: 숫자 배열에서 최대값을 찾으려 할 때, Math.max() 함수에 배열의 원소들을 전달하기 위하여 apply() 메서드를 사용


7. 함수 유효 범위와 클로저

/* ... */  : 생략


8. Function() 생성자

: 함수는 일반적으로 함수 정의 문이나 함수 리터럴 표현식의 function 키워드를 사용하여 정의됨.

   또한, Function() 생성자를 사용해서도 정의 될 수 있다. 잘 사용하지는 않는다.


ex) var f = new Function("x", "y", "return x*y;");

는 function f(x, y) { return x*y;} 와 완전히 동일하다.


- Function() 생성자를 사용하면 실행시점에 자바스크립트 코드를 동적으로 생성하고 컴파일할 수 있다. 이러한 점에서 Function() 생성자는 전역함수인 eval()함수와 유사하다.


- Function()생성자는 호출될 때마다 함수 몸체를 파싱하고 새로운 함수 객체를 생성한다. 따라서 만약 생성자 호출이 루프 안이나 자주 호출된는 함수 안에서 이루어진다면, 이러한 작업은 비효율적일 수 있다.


- Function() 생성자의 가장 중요한점은 생성된 함수가 어휘적 유효범위를 사용하지 않는다는 것.

대신에 Function() 생성자에 의해 생성된 함수는 마치 최상위 레벨의 함수 인것 처럼 컴파일 됨


ex) var y = 'global';

function constructFunction(){

var y = 'local';

return new Function('return y'); // 이 함수는 지역 유효범위를 포착하지 않는다.

}


// 이 소스는 'global'을 출력한다. 이는 Function() 생성자에 의해 변환된 함수가

// 지역 유효 범위를 사용하지 않기 때문이다.

// 만약 함수 리터럴 대신 사용했다면 다음 코드는 'local'을 출력할 것이다.

alert(constructFunction()()); // 'global'을 출력한다.


반응형

'Javascript > Book Study' 카테고리의 다른 글

Projavascript 9장 ThickBox 예제  (0) 2012.09.07
9장 클래스, 생성자, 프로토타입  (0) 2012.09.03
7장 객체와 배열  (0) 2012.08.14
6장 문장  (0) 2012.08.14
5장 표현식과 연산자  (0) 2012.08.09
Comments