Search

'IT/JavaScript'에 해당되는 글 7건

  1. 2009/10/14 DOM 간단 히스토리
  2. 2008/10/31 JavaScript #3 함수-5
  3. 2008/10/26 JavaScript #3 함수-4
  4. 2008/10/25 JavaScript #3 함수-3
  5. 2008/10/21 JavaScript #3 함수-2
  6. 2008/10/17 JavaScript #2 함수-1
  7. 2008/10/15 JavaScript #1 객체 (1)

DOM 간단 히스토리

IT/JavaScript 2009/10/14 11:49 Posted by Gony Taegony
1. Legacy DOM
   - 1996년 Netscape Communication Navigator 2.0 은 JavaScript를
     Internet Explorer 3.0 은 JScript (a part of JavaScript) 를 릴리즈 함.
   - 이 스트립트들은 제한된 detecting user-generated events 기능과 HTML 수정 기능을 제공함.
   - 이후 이를 DOM Level 0 라고 함.
   - 엑세스 할 수 있는 elements 가 제한됨.
   - Form, link, image elements 는 root document object로 시작하는
     계층적 이름 (hierarchical name)을 통해서만 접근이 가능함.
   - 계층적 이름 (hierarchical name)은 names 또는
      the sequential index of traversed elements 로 만들어짐.
      ex) names : document.formName.inputName
          index : document.forms [0].elements [0]
   - client side 의 form validation과 rollover 기능이 가능함.
2. Intermediate DOM
   - 1997년 Netscape Navigator, Internet Explorer 4.0 은 DHMTL 기능을 추가 지원함.
   - DHTML은 로딩된 HTML을 변경하는 기능 : Legacy DOM 을 확장
   - JScript 가 JavaScript 를 기반으로 되어 있기 때문에 큰 틀에서는 호환성
     (Largely Compatible)을 가짐에도 불구하고 DHTML DOM extension 이 벤더별로
     각각 개발됨으로 인해 서로 비호환성을 가지게 되었다.
   - 이 DOM 버전을 Intermediate DOM 이라고 한다.
   - Display 에 영향을 주는 CSS properties 를 다룰 수 있다.
   - Layer 라고 불리우는 new feature 에 접근할 수 있다.
     ex) Netscape : document.layers 로 접근
         Microsoft : document.all 로 접근
   - 이 후 후속 버전에서는 Intermediate DOM 에 대하여 Netscape 는 호환성을 포기,  
     Microsoft 는 backward compatibility 를 유지함.
3. Standardization
   - W3C (World Wide Web Consortium) 에서 주관함.
   - 1997년 ECMAScript 를 발표
     : JavaScript 와 JScript 는 cross-browser compatibility를 위해 ECMAScript 를 구현함.
     : 이 후 DOM 표준화를 진행함.
   - 1998년 DOM Level 1 을 발표
     : document 의 어떤 위치의 element 든 바꿀 수 있는 방법을 포함하여 전체적인
       HTML, XML 에 대한 complete medel 을 제안함.
     : 그러나 2000년 까지 표준을 따르지 않는 Netscape 4.x, Explorer 4.x 가 계속 사용됨.
   - 2000년 DOM Level 2 를 발표
     : getElementById, event model, XML Namesapces, CSS 등을 도입함.
   - 2004년 DOM Level 3 를 발표
     : XPath, keyboard event handling, interface for serializing document as XML 를
       추가 지원함.

출처 : wikipedia
TAG DOM

JavaScript #3 함수-5

IT/JavaScript 2008/10/31 00:35 Posted by Gony Taegony
14. Currying (커링)
  - 함수와 인수를 결합하여 새로운 함수를 만들 수 있게 한다.
  - 하나의 파라미터를 가진 함수를 여러번 호출하는 것과 같은 방법으로
    여러 개의 파라미터를 가진 함수로 변형하는 것을 말한다.
  - 자바스크립트는 자체적으로 currying 메소드가 없으므로 아래와 같이 구현한다.
  - 개인적으로 어디다 이런 기능을 써야할지는 아직 잘 모르겠다.
[code javascript]
var print = function (strLog) {
    document.write (strLog);
    document.write ('<br>');
};

// 함수 객체에 method 추가
Function.prototype.method = function (name, func) {
    if (!this.prototype[name]) {
        this.prototype[name] = func;
    }
};

Function.method ('curry', function () {
     // Array 객체의 slice 메소드를 가져온다.
    var slice = Array.prototype.slice;
     // Array 함수 객체에서 가져온 slice를 실행하는데
     // apply를 사용하여 this객체를 arguments로 바꿔준다.
     // 추후 Array의 concat을 사용하기 위함이다.
     // 왜냐하면 arguments는 length 메소드만을 지원하는 배열이다.
     // 따라서 엄밀히 말하면 배열 객체가 아니다.
     // 아래구문은 arguments를 배열객체로 만들어 args에 할당한다.
    var args = slice.apply (arguments);
     // that 은 curry 메소드를 사용하는 함수 객체를 가리킨다.
    var that = this;
     // curry 함수를 호출한 함수 객체를 변경한다.
     // 변경된 함수 객체를 호출하면 arguments와
     // 처음 curry 메소드 호출시 받은 arguments를
     // 합치게 된다.
    return function () {
        return that.apply (null, args.concat (slice.apply (arguments)));
    };
});

// 단순히 arguments를 모두 더해서 리턴하는 함수객체이다.
var add = function () {
    var iIndex = 0;
    var iCount = arguments.length;
    var iSum = 0;

    for (iIndex = 0; iIndex < iCount; iIndex ++) {
        iSum += arguments[iIndex];
    }
    return iSum;
};

// curry 를 호출해서 add1에 할당된 함수 객체는
// 1 이라는 arguments를 다음에 호출할 때 사용한다.
var add1 = add.curry (1);
// 변경된 add1을 호출한 함수 객체는 1 과 6을
// arguments 로 가지게 되므로 7을 리턴하게 된다.
print (add1 (6)); // 7
[/code]

12. Memoization (메모이제이션)
  - 함수가 이전에 연산한 결과를 저장하고 있는 객체를 사용하는 기법을 말한다.
  - 아래 두 함수를 비교해보면 이 기능을 어디에 쓸지 알 것 같다.
[code javascript]
// 피보나치 수열 함수이다.
// 아래의 연산을 하기 위해서는 453번의 호출이 발생한다.
var fibonacci = function (n) {
    return n < 2 ? n : fibonacci (n - 1) + fibonacci (n - 2);
};

for (var iIndex = 0; iIndex <= 10; i += 1) {
    print ('// ' + i + ': ' + fibonacci (i));
}

// 0: 0
// 1: 1
// 2: 1
// 3: 2
// 4: 3
// 5: 5
// 6: 8
// 7: 13
// 8: 21
// 9: 34
// 10: 55

// 위의 함수를 아래와 같이 변경하면 29번의 호출만 발생한다.
// 그 중 18번은 메모이제이션 결과를 얻기위한 과정이다.
var fibonacci = function () {
    var memo = [0, 1];
    var fib = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = flb (n - 1) + flb (n - 2);
            memo[n] = result;
        }
        return result;
    };
    return fib;
} ();
[/code]

    - 아래와 같이 일반화 시킬 수 있다.
[code javascript]
// 결과를 저장할 배열과 메모제이션을 할 함수를 인자로 받는다.
var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo [n];
        // 메모에 새로 저장할 데이터이면 fundamental을 호출한다.
        if (typeof result !== 'number') {
            result = fundamental (shell, n);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};

// 피보나치 함수
var fibonacci = memoizer ([0, 1], function (func, n) {
    return func (n -1) + func (n - 2);
});

// 팩토리얼 함수
var factorial = memoizer ([1, 1], function (func, n) {
    return n * func (n - 1);
});
[/code]

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

JavaScript #3 함수-4

IT/JavaScript 2008/10/26 02:58 Posted by Gony Taegony
11. 콜백
  - 비연속적인 이벤트를 다루는데 좀더 효율적인 방법이다.
  - 예를들어 서버로부터 응답을 기다리지 않고 바로 리턴을 한 후 응답이 왔을 때
     해당 함수를 호출하는 것이 더 효율적이다.
[code javascript]
// 이 예제는 개념적인 설명이므로 함수 이름에 신경쓸 필요가 없다.

// send_request_synchronously 함수를 호출하면
//  리턴값이 올 때까지 대기해야한다.
request = prepare_the_request ();
response = send_request_synchronously (request);
display (response);

// send_request_asynchronously 함수는 호출즉시 바로 리턴되며
// 리턴값이 오면 함께 넘긴 함수를 직접 호출해준다.
request = prepare_the_request ();
send_request_asynchronously (request, function (response) {
        display (response);
    });
[/code]

12. 모듈
  - 모듈은 내부의 상태나 구현 내용을 숨기고 인터페이스만 제공하는 함수나 객체이다.
  - 함수와 클로저를 사용하면 모듈을 만들 수 있다.
  - 예제1 : String 객체에 deentityify 메소드를 추가한다.
               이 메소드는 문자열에서  HTML 엔터티를 찾고 상응하는 문자열로 대체한다.
[code javascript]
var print = function (strLog) {
    document.write (strLog);
    document.write ('<br>');
};
// 엔터티의 이름과 상응하는 문자들이 담긴 객체가 필요하다.
// 이 객체를 위치할 수 있는 부분은
// 1. 전역변수 - 가능한 사용을 하지 말아야 한다.
// 2. 함수 내에 정의 - 호출시 마다 객체화를 시켜야하기 때문에 실행시간 비용이 부담된다.
// 3. 클로저에 두고 이 객체를 access 할 수 있는 메소드를 따로 둔다.

// 함수 객체에 method 추가
Function.prototype.method = function (name, func) {
    if (!this.prototype[name]) {
        this.prototype[name] = func;
    }
};

String.method ('convertHTML', function () {
    var entity = {
        quot: '"',
        lt: '<',
        gt: '>'
    }

    return function () {
        return this.replace (/&([^&;]+);/g, function (a, b) {
                var r = entity[b];
                return typeof r ==== 'string' ? r : a;
            }
        );
    } ()); // 호출한 결과 리턴

print ('&lt;&quot;&gt;'.convertHTML ()); // <">
// string.replace (/&([^&;]+);/g, function (a, b) { 에서
// a 는 검색한 문자열, b 는 정규식으로 찾은 문자열을 말한다.
[/code]
  - 모듈 패턴은 안전한 객체를 생성하는데도 사용된다.
[code javascript]
var serial_maker = function () {
    var prefix = '';
    var seq = 0;
    return {
        set_prefix : function (p) {
            prefix = String (p);
        },
        set_seq : function (s) {
            seq = s;
        },
        gensym : function () {
            var result = prefix + seq;
            seq += 1;
            return result;
        }
    };
};

var seqer = serial_maker ();
seqer.set_prefix ('Q');
seqer.set_seq (1000);
var unique = seqer.gensym (); // Q1000
// set_prefix 나 set_seq 를 거치지 않으면 직접
// var prefix, var seq 를 접근할 수 있는 방법이 없다.
// 앞에서 배운 this, that 방법을 사용한 것도 아니기 때문에 불가능하다.
// serial_maker 가 정의한 메소드만 가능하다.

// 아래는 확장해서 접근하려는 예
seqer.get_prefix = function () {
   return prefix;
};
try
{
    print (seqer.get_prefix ());
}
catch (e) {
    print (e.name + ': ' + e.description);
} // ReferenceError: undefined
[/code]

13. 연속 호출 (Cascade)
  - 만일 모든 메소드가 this를 반환한다면 연속적인 호출이 가능하다.
[code javascript]
var cascade = {
    method1: function () {
        print ('1');
        return this;
    },
    method2: function() {
        print ('2');
        return this;
   }
};
cascade.method1 ().method2 ();
/* 결과
1
2
*/
[/code]

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

JavaScript #3 함수-3

IT/JavaScript 2008/10/25 01:41 Posted by Gony Taegony
10. Closure
  - 내부 함수에서 자신을 포함하고 있는 외부 함수의 매개변수와 변수들을 접근할 수 있다.
    : 단, this와 arguments는 예외
  - 이 기능을 이용하면 아래와 같이 private 속성을 구현할 수 있다.
[code javascript]
var print = function (strLog) {
    document.write (strLog);
    document.write ('<br>');
};

// myObject는 함수의 실행 결과를 리턴받았기 때문에
// 외부에서 함수의 내부 변수 (var value)에 접근할 수 없다.
// 따라서 함수 내부에서 정의된 개체를 통해서만 접근할 수 있다.
var myObject = function () {
    var value = 0;

    return {
        increment: function (inc) {
            value += typeof inc === 'number' ? inc : 1;
        },
        getValue: function () {
            return value;
        }
    };
} (); // 함수의 실행한 결과를 myObject에 할당한다.

print (myObject.value); // undefined
print (myObject.getValue ()); // 0
[/code]
  - 내부 함수가 외부 함수에 있는 변수의 복사본이 아니라 실제 변수에 접근한다.
[code javascript]
<html>
<header>
<script language='javascript'>
    var add_the_handlers = function (nodes) {
        var i;
        // 원하는 기능은 각 노드에 유일한 키값을 할당하는 것이고
        // onClick이벤트가 발생하면 키값을 출력하도록 하는 것이다.
        // 하지만, Closure 기능에 의해
        // alert (i)가 호출되면 외부 함수의 var i값을 사용하게 된다.
        // 외부 함수의 var i 는 이미 4로 바뀌어 있으므로
        // onClick 이벤트가 발생하면 모두 4를 출력한다.
        // 따라서 다음 코드블럭 처럼 수정해야한다.
        for (i=0; i<nodes.length; i+=1) {
            nodes[i].onclick = function (e) {
                    alert (i);
            };
        }
    };
</script>
</header>
<body onLoad='javascript:add_the_handlers (document.frmText);'>
    <form name='frmText'>
    <input type='textbox' name='txt1' value='0'><br>
    <input type='textbox' name='txt2' value='1'><br>
    <input type='textbox' name='txt3' value='2'><br>
    <input type='textbox' name='txt4' value='3'><br>
    </form>
</body>
</html>
[/code]
[code javascript]
var add_the_handlers = function (nodes) {
    var i;
    // 편의상 i를 iIndex로 사용했다.
    // 넘겨받은 iIndex 값을 사용하기 때문에 의도한대로 정상출력된다.
    for (i=0; i<nodes.length; i+=1) {
        nodes[i].onclick = function (iIndex) {
            return function (e) {
                alert (iIndex);
            };
        } (i);
    }
};
[/code]
  - 이벤트 함수 출력을 해보려고 print (document.frmText[2].onClick);을
    호출해보았으나 undefined 로 출력되었다. 이유는 모르겠다.
    그래서 한김에 아래와 같이 수행해 보았다. 별의미는 없지만 ~ ^^;
[code javascript]
var arrFunc = [];
var testFunc = function () {
    var iIndex;
    for (iIndex = 0; iIndex < 2; iIndex ++) {
        arrFunc[iIndex] = function (iIndex) {
            return function () {
                return (iIndex);
            }
        } (iIndex);
    }
};
testFunc ();
var iIndex;
for (iIndex = 0; iIndex < arrFunc.length; iIndex ++) {
    print (arrFunc[iIndex]); // 배열에 저장된 함수 및 값을 출력한다.
    print ('arrFunc[' + iIndex + ']=' + arrFunc[iIndex]());
}
/* 실행 결과
function () { return iIndex; }
arrFunc[0]=0
function () { return iIndex; }
arrFunc[1]=1
*/
[/code]

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

JavaScript #3 함수-2

IT/JavaScript 2008/10/21 01:26 Posted by Gony Taegony
4. 인수 배열 (arguments)
  - 함수를 호출할 때 전달된 모든 인수를 접근할 수 있게 한다.
    : 매개변수 개수보다 더 많이 전달된 인수도 포함한다.
[code javascript]
var print = function (log) {
    document.write (log);
    document.write ('<br>');
};

var sum = function () {
    var i, sum = 0;
    // arguments 는 length라는 속성은 있지만
    // 모든 배열이 가지고 있는 메소드가 있는 것은 아니다.
    // - 저자는 설계상의 문제로 지적했다.
    for (i = 0; i < arguments.length; i += 1) {
        sum += arguments[i];
    }
    return sum;
};
print (sum(4, 8, 15, 16, 23, 42)); // 108
[/code]

5. 반환
  - 함수는 항상 값을 반환한다.
    : 반환값이 없는 경우 undefined가 반환된다.
  - 함수를 new 라는 전치 연산자와 함께 실행하고 반환값이 객체가 아닌 경우
    반환값은 this (새로운 객체)가 된다.
    : 아래와 같이 생성자 호출 패턴에서 객체를 반환하도록 해보면
      new라고 하는 키워드의 의미가 사라진다. (8번째 라인)
[code javascript]
var myObject = function () {
    return {
        name : 'taegony',
        age : 10
    }
}();

var Quo = function (string) {
    this.status = string;
    return myObject;
};

Quo.prototype.get_status = function () {
    return this.status;
};

var myQuo = new Quo ('confused');
print (myQuo.age); // 10
print (myQuo.status); // undefined

if (myQuo === myObject) {
    print ('same');
}
else {
    print ('not same');
} // same (myQuo와 myObject는 같은 객체이다)
[/code]

6. 예외
  - throw문은 name, message 속성을 가진 예외 객체을 반환한다.
  - 예외 객체는 try 문의 catch 절에 전달된다.
  - try 문은 하나의 catch 블록을 가진다.
    : 따라서 catch 내에서 예외 객체의 name으로 종류를 구분해야한다.
[code javascript]
var add = function (a, b) {
    if (typeof a !== 'number' ||
       typeof b !== 'number') {
        throw {
            name : 'TypeError',
            message : 'add needs numbers'
        };
    }
    return a + b;
}

var try_it = function () {
    try {
        add ('seven');
    }
    catch (e) {
        print (e.name + ': ' + e.message);
    }
}

try_it (); // TypeError: add needs numbers
[/code]

7. 기본타입에 기능 추가하기
  - 자바스크립트는 기본타입에 기능 추가를 허용한다.
  - Object.prototype 또는 Function.prototype에 추가한다.
[code javascript]
// 모든 함수객체에 method라고하는 property를 추가한다.
// 내부에 정의된 property가 없으면 추가한다.
Function.prototype.method = function (name, func) {
    if (!this.prototype[name]) {
        this.prrototype[name] = func;
    }
};

Number.method ('integer', function () {
    return Math[this < 0 ? 'ceil' : 'floor'] (this);
});
print ((-10 / 3).integer()); // -3

String.method ('trim', function () {
    return this.replace (/^\s+|\s+$/g, '');
});
print ('"' + "    neat    ".trim () + '"'); // neat

// Number, String은 함수객체이다.
print (typeof String); // function
print (typeof Number); // function
[/code]

8. 재귀적 호출
  - 웹브라우져의 DOM(Document Object Model) 같은 트리 구조를 다루는데 효과적인다.
  - Tail reursion (꼬리 재귀) 최적화를 지원하지 않는다.
[code javascript]
<html>
<header>
<script language='javascript'>
var walk_the_DOM = function walk (node, func) {
    func (node);
    node = node.firstChild;
    while (node) {
        walk (node, func);
        node = node.nextSibling;
    }
}

// 인자 : attribute, value (value 는 optional)
var getElementsByAttribute = function (att, value) {
    var results = [];
    walk_the_DOM (document.body, function (node) {
        var actual = node.nodeType === 1 &&
                         node.getAttribute (att);
        if (typeof actual === 'string' &&
                    (actual === value ||
                     typeof value !== 'string')) {
            results.push (node);
        }
    });

    alert (results);
    // [object HTMLInputElement], [object HTMLInputElement]
};
</script>
</header>
<body onload="getElementsByAttribute ('value')">
    <input type='textbox' name='txt1' value='txt1Value'>
    <input type='button' name='btn1' value='btn1Value'>
</body>
</html>
[/code]

9. Scope
  - C언어 유형의 블록 scope를 제공하지 않는다.
  - 하지만 함수 scope는 제공한다.
    : 함수 내에서 정의된 매개변수와 변수는 함수 외부에서 유효하지 않다.
      함수 내에서 정의된 변수는 함수 어느 곳에서도 접근할 수 있다.
      : 내부 함수에서 자신을 정의한 외부함수의 매개변수와 변수에 접근할 수 있다.
        (closure 라고한다.)
  - 함수에서 사용하는 모든 변수는 가능하면 첫 부분에 선언하도록 한다.
[code javascript]
var foo = function () {
    var a = 3, b = 5;
    var bar = function () {
        var b = 7, c = 11; // a = 3, b = 7, c = 11
        a += b + c; // a = 21, b = 7, c = 11
    };
    bar ();
    // a = 21, b = 5, c = undefined
};
[/code]

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

JavaScript #2 함수-1

IT/JavaScript 2008/10/17 02:00 Posted by Gony Taegony
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]

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

JavaScript #1 객체

IT/JavaScript 2008/10/15 01:45 Posted by Gony Taegony
1. 객체 리터럴
  - 아무 것도 없거나 하나 이상의 이름/값 쌍들을 둘러싸는 중괄호이다.
  - 속성 이름은 어떤 문자열이라도 가능 (빈 문자열 포함) 하다.
  - 속성 이름이 유효한 이름이고 예약어가 아니면 따옴표는 생략가능하다.
[code javascript]
var objHello = {};
var objName = {
    "first-name": "Tae Gon",
    "last-name": "Kim", // '-' 이 있으므로 따옴표 사용
    number: 9876  // 유효하고 예약어가 아니므로 따옴표 생략
};
[/code]

2. 속성값 읽기/갱신/추가
  - 대괄호([])를 사용하여 읽는다.
  - 유효한 이름이고 예약어가 아닌 경우 마침표(.)를 대신 사용가능하다.
  - 존재하지 않는 속성을 읽으면 undefined 반환한다.
  - undefined 속성을 참조하려고 하면 TypeError 예외가 발생한다.
  - 존재하는 속성에 값을 할당하면 갱신된다.
  - 존재하지 않는 속성에 값을 할당하면 속성이 추가된다.
[code javascript]
document.write (objName["first-name"]); // Tae Gon 출력
document.write (objName.number); // 9876 출력
document.write (objName["middle-name"]); // undefined 출력

document.write (objName.mother); // undefined 출력
document.write (objName.mother.age); // TypeError 발생

// 예외 발생을 위해 다음과 같이 처리
var strValue = objName.mother && objName.mother.age;
document.write (strValue); // undefined 출력
[/code]

3. 객체는 참조 방식으로 전달된다.

4. 프로토타입
  - 객체 리터럴로 생성되는 모든 객체는 Object.prototype 객체에 연결된다.
  - 객체 생성시 해당 객체의 프로토타입이 될 객체를 선택가능하다.
  - 프로토타입 연결은 객체의 속성을 읽을 때만 사용한다.
  - 해당 속성이 객체에 없는 경우 프로토타입 객체에서 찾으려고한다.
    : prototype chain의 마지막인 Object.prototype까지 계속 이어진다.
    : 그래도 찾지 못하면 undefined를 반환한다.
    : 이것을 위임 (delegation)이라고 한다.
[code javascript]
// 함수를 new라는 전치 연산자와 함께 호출하면
// 호출한 함수의 prototype 속성의 값에 연결된 링크를 갖는 객체가 생성된다.
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        var F = function () {
        F.prototype = o;
        return new F();
    };
}
var objName2 = Object.create (objName);
[/code]

5. Reflection
  - 객체에 어떠한 속성들이 있는지 접근해서 확인하는 것을 말한다.
  - typeof, hasOwnProperty, for in 등을 사용한다.
[code javascript]
// hasOwnProperty 는 prototype chain을 바라보지 않는다.
document.writeln (objName.hasOwnProperty ('first-name')); // true
document.writeln (objName.hasOwnProperty ('middle-name')); // false

// 열거 방식으로 확인
// 이 경우 순서가 이름순으로 나온다는 보장이 없다.
var name;
for (name in objName) {
    if (typeof objName[name] !== 'function') {
        document.writeln (name + ': ' + objName[name]);
    }
}
[/code]

6. 삭제
  - 객체의 속성을 삭제한다.
[code javascript]
delete objName['first-name'];
document.writeln (objName['first-name']); // undefined
[/code]

7. 전역변수의 최소화
  - 자바스크립트는 전역변수만을 지원한다.
    : 이것은 프로그램의 유연성을 떨어뜨린다.
[code javascript]
// 전역변수 사용을 최소화하는 방법들중 하나로써
// 전역변수 하나를 컨테이너로 사용한다.
var MYAPP = {};
MYAPP.objName = {
    'first-name': 'Tae Gon',
    'last-name': 'Kim'
};
document.writeln (MYAPP.objName['first-name']);
[/code]

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