Laboratory/Develop

함수와객체

theking 2007. 6. 14. 19:41
1. 함수 (Function)

가. 함수란 무엇인가?

함수란 프로그램 수행의 일련의 과정을 하나의 단위로 묶어줄 수 있는 기능을 제공해 주는 방법이다. 이렇게 하나의 단위로 묶여서 함수를 이루는 일련의 명령어들의 집합은 언제든지 반복적으로 호출될 수 있다.

이미 이전 강좌를 통해 자바스크립트가 지원하는 일부 시스템 함수들을 사용한 예가 있다. 즉, alert(), document.write(), prompt() 등이 바로 이러한 함수에 해당되는 것이다. 이러한 함수들은 특정 기능을 위해 간단히 그 이름으로 참조되어 호출되지만, 호출될 때마다 정해진 일련의 작업절차를 수행하도록 되어있다.

나. 함수의 정의

함수의 일반적인 형태는 다음과 같다.
----------------------------------------------------------------------
     function 함수이름(매개변수들...) {
          함수 기능을 수행하기 위한 명령어들...
     }
----------------------------------------------------------------------
함수 이름을 명명하는 법칙은 기본적으로 변수 또는 객체 이름을 명명하는 방식과 동일하다.

함수에는 호출될 때마다 입력으로 사용되는 매개변수들이 지정된다. 이 매개변수들은 함수를 호출하는 쪽에서 함수를 사용하는 목적에 따라 적절한 값을 지정하여 함수를 호출하게 된다. 함수의 수행은 이러한 매개변수들의 값에 따라서 수행 결과가 영향을 받게된다.

매개변수를 이용하여 간단한 함수를 만들어보기로 한다.
----------------------------------------------------------------------
     function HelloWindow(name) {
          var helloStart = "안녕하세요, ";
          var helloEnd = "님. 반갑습니다.";
          alert(helloStart + name + helloEnd);
     }
----------------------------------------------------------------------
위의 함수에서는 호출될 때 name이라는 매개변수를 받도록 되어있다.
따라서 HelloWindow()를 호출하는 방법은 예를 들면, HelloWindow("김형훈"); 과 같이 하면 된다.

위의 예제에 사용된 name이라는 매개변수는 HelloWindow 함수 내에서만 그 효력을 갖는다. 함수 밖에서는 name이라는 이름으로 같은 내용을 참조할 수 없다. 이러한 특성은 함수 내에서 var 명령으로 정의된 변수들도 마찬가지이다. 이와 같이 하나의 변수가 사용 가능한범위를 변수의 참조범위(Variable Scope)라고 하며, 위에서 설명한 함수 내에서만 사용 가능한 변수들을 지역변수(Local Variable), 그리고 특별한 참조의 범위제한 없이 어느 곳에서나 참조 가능한 변수를 전역변수(Global Variable)이라고 한다.

다. 함수의 값 반환

함수는 그 실행을 마치고 나서 한개의 값을 결과값으로 호출한 쪽에다 반환할 수 있다. 함수의 결과값 반환은 return 이라는 명령어를 통해서 수행한다.
----------------------------------------------------------------------
     return 값;
----------------------------------------------------------------------
return 문장에서 값 부분에는 변수, 리터럴, 혹은 수식 등 각종 형태가 모두 사용가능하다. 심지어는, 또다른 함수를 호출하여 그 결과값을 바로 반환하는 형태도 가능하다.
     function func1() {
          return func2();
     }
return문에서 반환하는 값들을 괄호로 묶기도 한다.
     return (temp);

두 개의 값을 매개변수로 받아서, 그중 큰 값을 반환하는 함수를 생각해보자. 함수의 이름은 myMax라고 하기로 하고, 일단 함수를 작성했다고 가정하고 호출하는 쪽의 예를 들어보면,
     prompt("숫자 하나만 입력하면 안잡아묵지", val1);
     prompt("기왕 넣는 김에 한개만 더...", val2);
     alert("두 수 중 큰쪽은 " + myMax(val1, val2) + "이군요.");
즉, 함수를 사용한 그 자리에 실제로 어떤 값을 사용한 것처럼 사용할 수 있다. 그럼 이제, 실제로 myMax()라는 함수를 작성해보기로 한다.
     function myMax(num1, num2) {
          if (num1 > num2) {
               return num1;
          else {
               return num2;
          }
          }
     }
간단하게, if문을 이용하여 num1과 num2를 비교한 다음에, 큰 쪽의 값을 반환한다. 두 수의 값이 같은 경우에는 num1이든 num2든 같기 때문에 어떤 쪽을 반환해도 상관없지만, 위의 코드에서는 정확히 표현하자면, num2가 반환되게 된다. 위의 코드를 이전에 설명했던 조건연산자를 사용하여 더 간단하게 만들어 보자.
     function myMax(num1, num2) {
          return (num1 > num2) ? num1 : num2;
     }
이제 단 한줄의 코드로 간단히 표현되었다. 이처럼, 어떤 연산자, 혹은 구조를 사용하느냐에 따라서 코드의 분량이 상당히 차이가 날 수도 있다.

라. 재귀적 함수 (Recursive Function)

함수 내에서도 또 다른 함수의 호출이 가능하다. 그런데, 이렇게 특정 함수 내에서 호출하는 함수가 바로 자기 자신 함수일 경우에는 이러한 함수를 재귀적(Recursive) 함수라고 부른다.

재귀적 함수 개념을 설명할 때 단골로 소개되는 것이 바로 팩토리얼(factorial) 값 구하는 것이다. 팩토리얼이란 수학에서 다루는 연산의 일종으로, 예를 들어, 5! (5 팩토리얼 이라고 발음) 이면 5 * 4 * 3 * 2 * 1 로, 120이라는 값을 가지게 된다. 즉, 어떤 수 N 에 대하여,
     N ! = N * (N-1) * (N-2) * ... * 2 * 1
과같이 설명된다. 그런데, 위의 식을 자세히 살펴보면 다음과 같은 사실을 유도해 낼 수 있다.
     N ! = N * (N-1) ! = N * ( (N-1) * (N-2) * (N-3) * ... * 2 * 1 )
즉, N 팩토리얼은 N 곱하기 (N-1) 팩토리얼과 정의상 일치한다. 이러한 사실을 바탕으로 팩토리얼 값을 구하는 재귀적인 함수를 작성할 수 있다. 다음의 예를 보자.
     function factorial(num) {
          if (num > 1) {
               return num * factorial(num - 1);
          } else {
               return num;
          }
     }
재귀적인 함수에서는 가장 주의해야 할 것이, 재귀의 종료조건을 잘 판단하는 것이다. 잘못하면 재귀가 종료되지 않아서 무한 반복의 함정에 빠질 수 있기 때문이다. 팩토리얼 계산에서는 1 ! 을 종료 조건으로 삼는다. 즉, 1 ! = 1 이기 때문에, factorial(1) = 1 이 되도록 더이상 재귀적 호출을 하지 않고 값을 반환하기만 하는 것이다. 물론, 1 이상인 경우에는 매개변수값에 매개변수값보다 1이 작은 값의 팩토리얼을 곱한 값을 반환하는데, 이 때 사용되는 팩토리얼은 다시 자기 자신의 함수를 호출하는 형태가 된다.

재귀적 함수는 잘 사용하면 코드가 간결해지고, 개념이 단순해지는데 반해서 일반 반복문(Loop)을 사용하는것 보다 수행성능이 낮아질수도 있고, 코드 상의 약간의 실수도 치명적인 결과를 초래할 수 있기 때문에 사용상의 주의가 요구된다.


2. 객체(Object)의 구성

자바스크립트에서 다루는 객체는 지난 강좌에서도 설명한 바와 같이, 시스템 즉 자바스크립트 자체기능으로서 제공하는 내장 객체(Built-in Objects)와 사용자가 직접 특정 목적에 맞게 만들어서 사용하는 사용자 정의 객체(User-defined Objects)가 있다. 지금부터 설명할 내용은 주로 사용자 정의 객체를 만들기 위한 방법과 관련된 내용들을 주로 다루도록 한다.

가. 객체의 속성(Property) 정의

객체를 만들기 위해서는 먼저, 객체의 이름이 필요하다. 또한 객체를 구성하는 구성요소들을 정의하는 절차가 필요하다. 물론, 객체를 구성하는 구성요소 또한 그 객체 내에서 유일한 이름을 갖게 된다. 객체는 그 객체를 표현하는 정보를 속성이라는 저장소에 보관한다. 이러한 속성들은 각자 나름대로 하나의 객체 내에서 유일한 이름들을 가진다. 이렇게, 객체를 정의하기 위해 객체의 이름, 객체 내의 속성 이름 및 속성의 값들을 지정하는 대표적인 방법으로는 생성자(Constructor)를 이용하는 방법이다.

생성자는 하나의 함수로 표현되며, 함수의 이름은 객체를, 함수 내에서 수행되는 내용은 객체의 속성들의 값을 지정하는 것이다. 다음의 예를 보자.
----------------------------------------------------------------------
     function student(name, age, grade) {
          this.name = name;
          this.age = age;
          this.grade = grade;
     }
----------------------------------------------------------------------
위의 내용은 student라는 객체를 정의하는 생성자의 예제이다. 위 예제에서는 3개의 매개변수를 받아서, student의 속성, 즉 학생의 이름과 나이, 그리고 점수를 정의한다.

위 예제에서는 지금까지 설명하지 않은 예약어인 this를 사용했다. this는 "현재 객체"를 나타내는 자바스크립트 예약어로, 여기서는 this가 student 객체를 나타내는 것이 된다.

이제 생성자가 준비되었으므로, 이 생성자를 이용하여 실제로 객체를 어떻게 만드는가에 대해서 알아보도록 한다. 위의 student라는 것은 실제로는 생성되는 객체의 종류를 나타내는, 정확히 표현하자면 "클래스"에속하는 것이다. 이제 babo라는 이름의 학생을 이 생성자를 이용해 실제로 만들어보려면 다음과 같이 기술하면 된다.
     babo = new student("SYLee", 30, 15);
     // 예제에 사용된 이름과 수치는 특정인물과 관계없음 :P..
위와 같은 문장을 통해 babo라는 이름의 객체가 생성된다. babo 객체는 name 속성이 "SYLee", age 속성이 30, 그리고 grade 속성이 3이 된다.

이미 만들어진 객체의 속성 값을 변경시키는 것도 가능하다. 해가 바뀌어서 나이가 한살 더 먹었다고 가정하고 객체를 변경한다.
     babo.age++;
babo 객체의 age속성을 1 증가시키는 문장이다.

나. 객체의 속성으로서의 객체

지금까지는 객체의 속성은 마치 변수처럼 한가지 값만을 가지는 경우를 설명하였다. 그러나, 속성 자체도 또다른 객체가 될 수 있다. 위의 예제에서는 점수를 한가지만 표시했는데, 점수에는 국영수 점수가 있다고 가정하고, 국영수 점수를 표현하기 위해 점수를 하나의 독립된 또다른 객체로 정의하여 사용하는 예제를 보도록 하자.
----------------------------------------------------------------------
     function gade(korean, english, math) {
          this.korean = korean;
          this.english = english;
          this.math = math;
     }

     baboGrade = new grade(20,10,5);

     babo = new student("SYLee", 30, baboGrade);
----------------------------------------------------------------------
점수 객체인 baboGrade를 먼저 생성하고, babo 객체를 만들때 매개변수로 이미 만들어놓은 baboGrade를 지정함으로써 babo 객체 내의 속성으로 baboGrade가 포함되도록 하는 것이 위 예제의 내용이다.

다. 객체에 메소드 붙이기

객체의 생성, 객체의 속성값 지정 등에 대해서알아보았다. 그러나, 이러한 객체의 특성들을 십분 활용하기 위해서는 메소드라는 날개를 달아야 진정한 객체의 활용이 가능할 것이다. 지금까지 student 객체와 이에 딸린 속성들을 정의하는 방법들에 대해서 알아보았다. 이제는 이 객체를 이용하는 메소드를 정의하는 방법에 대해서 알아본다. 다음은 student 객체의 내용을 출력하는 함수이다.
----------------------------------------------------------------------
     function displayProfile(){
          document.write("Name: " + this.name + "<BR>");
          document.write("Age: " + this.age + "<BR>");
          document.write("Grade(Korean): " + this.grade.korean + "<BR>");
          document.write("Grade(English): " + this.grade.english + "<BR>");
          document.write("Grade(Math): " + this.grade.math + "<BR>");
     }
----------------------------------------------------------------------
내용을 통해 알 수 있듯이, 여기서도 this라는 예약어를 사용해다. 따라서 이 함수는 student 객체가 현재 객체로 설정되어 있어야만 제대로 동작한다. 이를 위해서는, 객체에 메소드 함수를 연결시켜야만 한다. 다음은 객체 생성자에서 위 메소드를 붙여서 사용할 수 있도록 하는 예제이다.
----------------------------------------------------------------------
     function student(name, age, grade) {
          this.name = name;
          this.age = age;
          this.grade = grade;
          this.displayProfile = displayProfile;
     }
----------------------------------------------------------------------
마치 속성 하나를 첨가하는 것처럼, 단순히 메소드 함수의 이름을 지정하는 것으로써 객체와 메소드 간의 연결이 이루어졌다. 이렇게 연결된 메소드를 사용하는 방법을, 위에서 생성한 babo라는 객체를 예로 살펴본다.
     babo.displayProfile();
메소드 호출은 속성값 참조와 기본적으로 형태가 같으나, 뒤에 괄호()가 붙음으로써 이는 메소드 호출이라는 사실을 지정한다.

라. 조합 배열(Associative Array)

자바스크립트 이외의 다른 프로그래밍 언어를 이미 접해본 경험이 있는 사람의 경우에는 배열(Array)에 대하여 배운 적이 있거나 사용해본 경험이 있을 것이다. 배열은 여러개의 자료를 하나의 이름으로 등록하여,순서적인 번호로 그 내용을 참조할 수 있는 자료구조로서, 많은 양의 유사한 정보를 효과적으로 프로그램에서 제어할 수 있는 기능을 제공하는, 많은 프로그래밍 언어에서 기본적으로 제공하는 기능이다.

자바스크립트 언어에서도 C나 C++, 그리고 자바 언어에서와 거의 흡사한 형태로 배열의 사용법을 지원한다. 예를 들어 student라는 이름의 배열 속에 각각 값을 입력하는 문장을 보자면, 다음과 같다.
----------------------------------------------------------------------
     student[0] = "SYLee";
     student[1] = 30;
     student[2] = 15;
----------------------------------------------------------------------
배열의 사용은 배열이름 뒤에 대괄호([, ])를 적고, 그 안에 0 이상의 숫자를 지정하는 것으로 가능하다. 배열의 첫번째 원소는 0이라는 인덱스 번호를 가진다. 1부터 시작하는 것이 아니라는 것에 주의를 하자.

자바스크립트에서의 배열은 객체의 속성과 직접적으로 연결되어 있는 구조를 가진다. 즉, 객체의 속성은 실제적으로 내부적으로는 배열과 같이 사용된다는 것이다. 이러한 사실은 배열에서 각각의 원소를 참조하는 인덱스 번호를 숫자로 사용할 수도, 그리고 속성명으로 사용할 수도 있는 양면성으로 확인할 수 있다. 예를 들어 다음과 같은 배열원소 참조법도 가능하다.
----------------------------------------------------------------------
     student["name"] = "SYLee";
     student["age"] = 30;
----------------------------------------------------------------------
위의 student라는 배열은 실제로는 위에서 설명한 student 객체의 정의를 이미 했다고 가정했을때 사용할 수 있는 배열참조법이다. 또한, 어떤 객체를 이미 정의했다고 할 때, 그 속성들을 참조할 때도, object.property 식으로 참조할 수도 있지만, object[number] 식으로 속성을 정의한 순서대로 0부터 속성 갯수 - 1 개 까지의 인덱스 번호로 배열처럼 사용할 수도 있다.

출처:http://my.dreamwiz.com/bivas