본문 바로가기

IT/JavaScript

JavaScript #2 함수-1

1. 함수 객체
  - 함수는 객체이다.
    : 객체는 prototype 객체로 숨겨진 연결을 갖는 name/value 쌍들의 집합체이다.
    : 객체는 Object.prototype에 연결된다.
  - 함수 객체는 Function.prototype에 연결된다.
    : Function은 Object.prototype에 연결된다.
  - 모든 함수는 숨겨진 두 가지 속성이 있다.
    : context (함수의 문맥), code (함수의 행위를 구현)
  - 모든 함수 객체는 prototype이라는 속성이 있다.
    : prototype 속성은 객체이며 constructor 라는 속성을 포함하고 있다.
    : constructor는 함수 자체를 값으로 가진다.
  - 함수를 다른 객체와 구분 짓는 특징은 호출할 수 있다는 점이다.
  - 아래는 시험삼아 해본 코드들이다.
[code javascript]
// 칸띄우기 귀찮아서 넣은 함수
// 앞으로 계속 이놈을 사용할 예정
var print = function (log) {
    document.write (log);
    document.write ('<br>');


var myFunc = function () {
    print ('this is myFunc' );


myFunc (); // this is myFunc
print (typeof myFunc.prototype); // object
print (myFunc.prototype); // [object Object]

print (typeof Function.prototype); // function
print (Function.prototype);
// function Empty() { [Native code] }

print (typeof Object.prototype); // object
print (Object.prototype); // [object Object]

print ('Function.prototype.constructor = '
         + print.prototype.constructor);
// function (log) { document.write(log);document.write("
// ");}
// 함수 자체를 나타낸다.
// <br>은 html 태그이므로 화면상의 줄이 바뀌었다.
[/code]

2. 함수 리터럴
  - 함수 리터럴은 4가지 부분이 있다.
    : function, 함수명, 매개변수 집합, 중괄호로 둘러싸인 문장들의 집합
  - 함수 리터럴로 생성한 함수 객체는 외부 문맥으로의 연결이 있다.
    : 클로져 (closure)라고 한다.

3. 호출
  - 함수를 호출하면 매개변수, this, arguments가 넘어가게 된다.
  - this는 호출 패턴에 따라 다르게 초기화한다.
    : 호출 패턴은 메소드 호출, 함수 호출, 생성자 호출, apply 호출 패턴이 있다.
  - 함수를 호출하는 호출 연산자는 함수를 나타내는 표현식 뒤에 이어지는 한 쌍의 괄호이다.
  - 매개변수 수보다 초과하는 인수는 무시된다.
  - 매개변수 수보다 적은 경우 남은 매개변수는 undefined가 할당된다.
[code javascript]
// myObject 는 함수를 받는게 아니라 함수를 호출한 결과를 받는다.
var myObject = function () {
    return {
        name: 'taegony',
        age: 10
    }
}(); // 이 부분이 호출하는 부분이다.

print (myObject.name); // taegony
[/code]

3.1 메소드 호출 패턴
  - 함수를 객체의 속성에 저장하는 경우 이 함수를 메소드라고 한다.
  - this는 메소드를 포함하는 객체에 바인딩 된다.
  - this와 객체의 바인딩은 호출 시에 일어난다.
  - 자신의 객체 문맥을 this로 얻는 메소드를 public method라고 한다.
[code javascript]
var myObject_method = {
    value: 0,
    increment: function (inc) {
        this.value += typeof inc === 'number' ? inc : 1;
    } // '===' 는 type과 value가 같은 경우가 참이다.
};

myObject_method.increment ();
print (myObject_method.value); // 1

myObject_method.increment (2);
print (myObject_method.value); // 3
[/code]

3.2 함수 호출 패턴
  - 함수가 객체의 속성이 아닌 경우 함수로서 호출한다.
  - this는 전역객체에 바인딩된다.
    : 이 책의 저자는 이 경우를 언어의 잘못된 설계로인해 생긴 문제라고 본다.
      객체의 메소드가 내부 함수를 가지는 경우
      내부 함수에서 this는 자신을 포함한 객체를 가리키는 것이 라니라
      전역객체를 가리키게 되기 때문이다.
  - 전역객체 문제에 대한 대안으로 아래와 같은 방법을 설명했다.
[code javascript]
var add = function (a, b) {
    return a + b;
}
// 이전에 사용한 myObject에 double이라는 메소드를 추가한다.
// 이 때 아래 정의된 helper 함수에서 this는 전역객체를 가리키므로
// double 메소드의 this를 that 변수로 할당하여 helper 함수에서 사용한다.
myObject.double = function () {
    var that = this;
    var helper = function () {
        that.age = add (that.age, that.age);
    }
    helper ();
}
print (myObject.age); // 10
myObject.double ();
print (myObject.age); // 20
[/code]

3.3 생성자호출 패턴
  - 함수를 new 연산자와 함께 호출하면 호출된 함수의 prototype 속성의 값에
    연결되는 (숨겨진) 링크를 갖는 객체가 생성되고,
    이 새로운 객체는 this에 바인딩 된다.
  - 생성자 함수를 new없이 사용하면 경고없이 그냥 넘어간다.
     따라서 실수를 방지하기 위해 첫번째 문자를 대문자로 표기한다.
[code javascript]
// 생성자 함수 정의한다.
// 여기서 this는 새로운 객체를 가리킨다.
var Quo = function (string) {
    this.status = string;
};
// public method를 정의한다.
Quo.prototype.get_status = function () {
    return this.status;
};
// 새로운 객체를 생성한다.
var myQuo = new Quo ('confused');
print (myQuo.get_status); // confused
print (myQuo.status); // confused
[/code]

3.4 apply 호출 패턴
  - apply 메소드는 함수를 호출할 때 사용할 인수들의 배열을 받아들인다.
  - this의 값을 선택할 수 있도록 해준다.
  - apply 메소드는 두 개의 매개변수를 가진다.
    : 첫 번째는 this이고, 두 번째는 매개변수들의 배열이다.
[code javascript]
// this는 null, 매개변수는 3과 4를 넘긴다.
var array = [3, 4];
var sum = add.apply (null, array);
print (sum); // 7

// statusObject 개체를 선언하고
// Quo.prototype.get_status 메소드의 this값을 statusObject로 변경한다.
// 따라서 Quo.prototype.get_status는 statusObject.status를 리턴하게 된다.
var statusObject = {
    status: 'A-OK'
};
var status = Quo.prototype.get_status.apply (statusObject);
print (status); // A-OK
[/code]

공부한 책 : 자바스크립트 핵심가이드 - 더글라스 크락포드