javascript 완벽 가이드 정리

25
디디디 디디 Microsoft Script Debugger FireFox : Venkman 디디디디디디 디디디디 디디 디디디디 디디디디디 디디 디디 jslint http://jslint.com 2 디 디디 디디(lexical structure) 디디디 디 디디 디디 디 디디디 디디디 디디디디디디, 디디디디디디디 디디디디 디디디디디 디디디. return true; (디디디 디디디) ⇒ return true; 3 디 디디디 디디디 디 디디디 디디 디디디 Infinity NaN Number.MAX_VALUE Number.MIN_VALUE Number.NaN Number.POSITIVE_INFINITY Number.NEGATIVE_INFINITY var n = 17; n.toString(2); // ‘1001’ n.toString(8); // ‘021’ n.toString(16); // ‘0x11’ var n = 123456.789; n.toFixed(0); // 123456 n.toFixed(2); // 123456.79

Upload: etribestg

Post on 29-Nov-2014

286 views

Category:

Education


8 download

DESCRIPTION

책정리?

TRANSCRIPT

Page 1: Javascript 완벽 가이드 정리

디버거 종류

Microsoft Script DebuggerFireFox : Venkman

자바스크립트 코드에서 흔히 발생하는 문제점들을 찾아 주는 jslinthttp://jslint.com

2 장 어휘 구조(lexical structure)

코드를 두 줄로 나눌 때 앞줄의 온전한 문장형태라면, 자바스크립트는 자동으로 세미콜론을 삽입함. returntrue; ( 잘못된 표현임)

return true;⇒

3 장 데이타 타입과 값 특수한 숫자 상수들

InfinityNaNNumber.MAX_VALUENumber.MIN_VALUENumber.NaNNumber.POSITIVE_INFINITYNumber.NEGATIVE_INFINITY

var n = 17;

n.toString(2); // ‘1001’n.toString(8); // ‘021’n.toString(16); // ‘0x11’

var n = 123456.789;

n.toFixed(0); // 123456n.toFixed(2); // 123456.79n.toExponential(1); // 1.2e+5n.toExponential(3); // 1.235e+5n.toExponential(4); // 1.235e+5n.toExponential(7); // 123456.8 (?)

var product = “21” * “2”; // 두 문자열 곱은 숫자 42 가 된다.

Page 2: Javascript 완벽 가이드 정리

var number = string_value - 0; // 문자열 값에 0 을 더하면 타입 변환이 수행되는 것이 아니라 문자열 이어붙이기가 수행된다는 것을 주의하라

var number = Number(string_value);

parseInt(), parseFloat() 를 사용하라.

parseInt(“3 blind mice”); // return 3parseFloat(“3.14 meters”); // return 3.14parseInt(“12.34”); // return 12parseInt(“0xFF”); // return 255

parseInt() 는 변환하려는 숫자의 기수를 지정하는 두 번째 전달인자를 받기도 한다.

parseInt(“11”, 2); // 3(1*2) + 1parseInt(“ff”, 16); // 255(15*16 + 15)parseInt(“zz”, 36); // 1295(35*36 + 35)parseInt(“077”, 8); // 63(7*8 + 7)parseInt(“077”, 10; // 77(7*10 + 7)

parseInt(“eleven”); // return NaNparseFloat(“$72.47”); // return NaN

불리언 값이 숫자 문맥에서 사용되면 true 는 1 로 false 는 0 으로 변환된다. 숫자가 불리언 값을 기대하는 곳에서 사용되면 0 이나 NaN 인 경우는 false

그 외의 경우는 true 로 변환된다.

문자열이 불리언 값을 기대하는 곳에 사용되면 빈 문자열인 경우는 false 로 그 외의 경우는 true 로 변환된다.

null, undefined 값은 false 로 기타 null 이 아닌 객체나 배열, 함수는 true 로 변환된다.

var x_as_boolean = Boolean(x);

var x_as_boolean = !!x;

자바스크립트의 중요한 특징중 하나는 함수도 자바스크립트 코드로 조작할 수 있는 형태의 값이라는점이다. 자바스크립트에서 함수가 실제로 값이라는 사실은 이 언어에 큰 유연성을 부여한다.

이것은 함수를 변수나 배열, 객체에 저장할 수 있으며 다른 함수의 전달인자로 넘겨 줄 수 있다는 것을의미한다.

함수 정의, 함수 리터럴 함수 리터럴은 함수 이름을 명시하지 않는다는 것을 제외하고는 함수 정의와 모양이 동일하다. 함수

정의와 함수 리터럴 간의 큰 차이점은 함수 리터럴은 자바스크립트 표현식 내에 나타날 수 있다는 점이다.

Page 3: Javascript 완벽 가이드 정리

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

이름 없는 함수를 프로그램 내에 리터럴 형태로 포함시킬 수 있게 한 최초의 언어인 Lisp 프로그램 언어를 기리는 의미에서 이러한 방식으로 정의된 함수를 람다함수(lambda function) 라고 부른다.

var square = new Function(“x”, “return x*x”;”); 이 방법도 있다.

3.5 객체객체(Object) 는 이름 붙은 값들의 모음이다. (??)

image.width; // image[“width”]image.height; // image[“height”]

객체 생성 객체를 생성하고 나면 마음대로 객체를 사용하고 프로퍼티 값을 설정할 수 있다.

var point = new Object();point.x = 2.3;point.y = -1.2;

객체 리터럴var point = { x:2.3, y:-1.2 };var rectangle = { upperLeft: {x:2, y:2},

lowerRight: {x:4, y:4}};

var square = {“upperLeft”: {x:point.x, y:point.y},‘lowerRight’: { x:{(point.x + side)}, y:{(point.y + side) }

};

null 이 아닌 객체가 불리언 문맥에서 사용되면 true 로 변환된다. 객체가 문자열 문맥에서 사용되면 객체의 toString() 메서드가 호출되고 이 메서드가 반환하는 문자열이 대신 사용된다. 객체가 숫자 문맥에서 사용되면 자바스크립트는 먼저 객체의 valueOf() 메서드를 호출한다.

3.6 배열 일반적인 배열은 음수가 아닌 정수로 인덱싱됨. 연관 배열은 문자열로 인덱싱.

자바스크립트는 다차원 배열을 지원하지 않음. 배열의 원소들이 모두 동일한 타입을 가질 필요가 없다.

var a = new Array();a[0] = 1.2; a[1] = “javascript”; a[2] = true; a[3] = { x:1, y:3 };

Page 4: Javascript 완벽 가이드 정리

var a = new Array(1.2, “javascript”, true, { x:1, x: 3});

Array() 생성자에 숫자 하나를 넘겨주면 그 숫자는 배열의 크기

var a = new Array(10);

정의되지 않은 원소 10 개를 포함한 새 배열을 생성한다.

대괄호 사용var a = [1.2, “javascript”, true, {x:1, y:3}];var matrix = [[1,2,3], [4,5,6], [7,8,9]];

var base = 1024;var table = [base, base+1, base+2, base+3];

쉼표 사이에 값을 생략하여 정의되지 않은 요수를 배열 리터럴 내에 포함시킬 수 있다.var sparseArray = [1,,,,,5];

null 불리언 문맥에서는 false 숫자 문맥에서는 0, “문자열 에서는 null” 이다

undefined 는 선언은 되었지만 값이 할당된 적이 없는 변수에 접근하거나, 존재하지 않는 객체 프로퍼티에 접근할 경우 반환되는 값이다. 이 특수한 undefined 값은 null 과 동일한 값이 아니다.

null, undefined 값은 서로 구별되는 값이지만 동등 연산자(equality operator) == 는 같은 것으로간주한다.

Error 객체Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError

문자열은 필요할 경우 String 객체로 자동 변환된다. 모든 숫자, 문자열, 혹은 불리언 값들은 Object() 함수를 사용하여 대응되는 래퍼 객체로 변환할 수 있다.

var number_wrapper = Object(3);

모든 객체들은 불리언 문맥에서 사용될 때 true 로 변환된다.new Boolean(false); // 내부 값은 false 이지만 객체는 true 로 변환된다.new Number(0);new String(“”);new Array();

배열의 toString() 메서드는 각 배열 원소를 문자열로 변환하고 배열 원소 사이에 쉼표를 삽입하여 이어 붙인 문자열을 결과로 반환한다. 따라서 아무 원소도 없는 배열은 빈 문자열로 변환되고 이것은 숫자 0 으로 변환된다. (valueOf)

Date 객체는 toString(), valueOf() 메서드를 + 연산에는 toString 을 비교연산(<,>, <=, >=) 에는

Page 5: Javascript 완벽 가이드 정리

valueOf 를 사용한다.

4 장 변수 프로퍼티의 이중성( duality )

var 문에서 변수의 초기값을 지정하지 않을 경우 변수 선언은 되지만, 값이 저장되기 전까지 값은undefined이다.

아직 var 문으로 선언되지 않은 변수에 값을 할당하려 하면, 자바스크립트가 암묵적으로 그 변수를선언한다. 단, 암묵적으로 선언되는 변수는 항상 전역변수로 선언된다. 설사 그 변수가 함수 안에서

쓰인다 하더라도 마찬가지다.

4.3.1 블록 단위의 유효 범위는 없다. 자바스크립트는 불록 단위의 유효 범위라는 것이 존재하지 않는다. 함수 안에서 정의된 변수는 그것이

정의된 위치와 관계없이 항상 함수전체에 걸쳐 유효하다.

놀라운 결과var scope = “global”;function f() {

alert(scope); // “global” “이 아닌 undefined” 를 표시한다.var scope = “local”; // 변수는 이곳에서 초기화 되었지만 함수 전체에 걸쳐 정의되어 있다.alert(scope); // “local” 을 표시한다.

}

5 장 표현식과 연산자=, ==, ==== 는 취하다(gets) 또는 할당하다(assigned), == 는 ~ 와 동등하다(is equal to), === 는 ~ 와 일치한다(is identical to) 라고 읽는다.

var point = { x:1, y:1 };“x” in point; // true“y” in point; // true“z” in point; // false

Page 6: Javascript 완벽 가이드 정리

“toString” in point; // 상속된 프로퍼티. true.

자바스크립트 객체의 클래스는 그 객체를 초기화하는 생성자 함수에서 정의된다.var d = new Date(); // Date() 생성자로 새로운 객체를 생성한다.d instanceOf Date; // true.d instanceOf Object; // true. 모든 객체는 Object 의 인스턴스.d instanceOf Number; // false

var a = [1,2,3]; // 배열a instanceOf Array; // truea instanceOf Object; // true.a instanceOf RegExp; // false

+ 연산자는 숫자 피연산자보다 문자열 피연산자에게 우선권을 부여한다.+ 연산자의 두 피연산자 중 하나가 문자열이면 ( 또는 객체이면) 다른 하나의 피연산자를 문자열로변환하고( 또는 두 피연산자 모두 문자열로 변환하고) 결과로 얻어지는 두 문자열을 이어 붙인다. (

숫자끼리의 덧셈이 아닌 것이다)

반면, 비교 연산자는 오직 두 피연산자가 모두 문자열인 경우에 한해서 문자열 비교를 수행한다. 하나의 피연산자만 문자열인 경우 자바스크립트는 이를 숫자로 변환하려 할 것이다.

1 + 2 // 덧셈. 3“1” + “2” // 이어 붙이기. “12” “1” + 2” // 이어 붙이기. “12”11 < 3 // 숫자 비교 false“11” < “3” // 문자열 비교 true

“11” < 3 // 숫자 비교. false“one” < 3 // 숫자 비교. “one” 이 NaN 으로 변환된다. false

s = 1 + 2 + “blind mice”; // “3 blind mice”t = “blind mice” + 1 + 2; // “blind mice: 12”+ 연산자가 왼쪽에서 오른쪽으로 적용된다.

delete 연산자

var o = {x:1, y:2}delete o.x; // 객체 프로퍼티 중 하나를 삭제한다. truetypeof o.x; // 존재하지 않는 프로퍼티, “undefined”delete o.x; // 존재하지 않는 프로퍼티, truedelete o; // 선언된 변수는 삭제할 수 없다. falsedelete 1; // 정수도 삭제할 수 없다. falsex = 1;delete x; // 이와 같은 종류의 변수는 삭제할 수 있다. true

Page 7: Javascript 완벽 가이드 정리

x; // 런타임 에러, x 는 정의되지 않았다.

var my = new Object(); my.hire = new Date();my.fire = my.hire;delete my.hire;document.write(my.fire); // my.fire 는 여전히 Date 객체를 참조하고 있다.

void 연산자

6 장 문장

throw

function factorial(x) {if(x < 0) throw new Error(“x must not be negative”);….

}

with

frame[1].document.forms[0].address.value;

with(frame[1].document.forms[0]) {name.value = “”;address.value = “”;email.value = “”;

}

7 장 객체와 배열

프로퍼티 열거하기

function DisplayPropertyNames(obj) {var names = “”;for (var name in obj) names += name + ‘\n’;alert(names);

}

7.3 연관 배열로서의 객체

object.propertyobject[“property”]

Page 8: Javascript 완벽 가이드 정리

두 자바스크립트 표현식은 완전히 동일한 값으로 평가된다. ⇒ 연관배열 (associative array)

연관배열은 동적으로 임의의 값과 임의의 문자열을 연관지어 저장할 수 있는 자료구조다.

7.4.1 constructor 프로퍼티

자바스크립트에서 모든 객체는 객체를 초기화하는데 사용되는 생성자 함수인 constructor 프로퍼티를 지니고 있다.

var d = new Date();d.constructor == Date // true

if( (type of == “object”) && (o.constructor == Date)) {}

if( (type of == “object”) && (o instanceOf Date)) {⇒}

toString()toLocaleString()valueOf() ⇒ 이 메서드는 자바스크립트가 객체를 문자열이 아니라 숫자 같은 다른 기본 타입으로

변환하려 할 때 호출된다.hasOwnProperty()

var o = {};o.hasOwnProperty(“undef”); // false o.hasOwnProperty(“toString”); // false : toString 은 상속받은 프로퍼티다.Math.hasOwnProperty(“cos”); // true

propertyIsEnumerable()

isPrototypeOf()var o = {};Object.prototype.isPrototypeOf(o); // true o.constructor == ObjectObject.isPrototypeOf(o); // falseo.isPrototypeOf(Object.prototype); // falseFunction.prototype.isPrototypeOf(Object); // true Object.cunstroctor == Function

7.5 배열var empty = [];var primes = [2,3,5,7,11];var misc = [1.1, true, ”a”,]; // length ?

Page 9: Javascript 완벽 가이드 정리

var base = 1024;var table = [base, base+1, base+2, base+3];

var b = [[1, {x:1, y:2}], [2, {x:3, y:4}]];

var count = [1,,3]; // 이 배열의 원소는 세개다. 가운데 원소는 정의되지 않았다.var undefs = [,,]; // 이 배열의 원소는 두 개다. 두 원소가 모두 정의되지 않았다.

var a = new Array();var a = new Array(5, 4, 3, 2, 1, “testing, testing”);

배열의 길이를 지정하는 숫자 값을 전달인자로 하여 호출하는 방법var a = new Array(10);

이 경우에는 생성자의 전달인자로 지정된 수치만큼원소를 갖는 배열을 생성한다. 각 원소의 값은undefined 이며 length 프로퍼티 값은 생성자의 전달인자에 명시된 수치이다.

배열의 인덱스에는 반드시 0 보다 크거나 같고 2^32-1 보다 작은 정수를 사용해야만한다. 만약 너무 큰 수나 음의 정수, 부동소수점 값, 불리언 값과 객체 같은 다른 값을 인덱스로 사용하려면 자바스크립트는 이를 문자열로 변환하고 이 문자열을 객체의 프로퍼티 이름으로 간주한다. 즉, 이것은 더 이상 배열의

인덱스가 아니다.

a[-1.23] = true;

자바스크립트 배열의 인덱스는 연속적이지 않아도 된다. 이것은 배열의 인덱스를 반드시 연속된 범위의 숫자 안에서 고르지 않아도 됨을 의미한다. 자바스크립트는 배열에 실제로 저장된 원소들에 대해서만

메모리를 할당하도록 구현할 수 있다. 즉, 다음과 같은 코드를 실행할 때에 자바스크립트 인터프리터는 0 번 인덱스와 10,000 번 인덱스를 위해서만 메모리를 할당하며 그 사이에 있는 9,999 개의 인덱스에

대해서는 메모리를 할당하지 않는다.

a[0] = 1;a[10000] = “this is element 10,000”;

// ???var c = new Circle(1,2,3);c[0] = “this is an array element of an object !”; // c[0] 는 객체의 배열 원소이다.

“이 예는 단지 객체에 0” 이라는 이름의 프로퍼티를 추가할뿐이다. 객체에 배열 원소를 추가한다고 해서 객체가 배열이 되지는 않는다.

7.5.2 배열 원소 삭제하기delete 연산자를 사용하면 배열 원소의 값을 undefined 값으로 설정할 수 있다.

Array.shift(), Array.pop(), Array.splice();

7.6.5 배열의 크기 조절하기

Page 10: Javascript 완벽 가이드 정리

배열의 length 프로퍼티는 읽고 쓸수 있는 값이다. length 프로퍼티는 현재의 값보다 작게 설정하면 배열은 그 새로운 길이로 축소된다. 즉 새롭게 설정된 배열의 길이를 벗어나는 위치의 원소들은 버려지고

그 원소들의 값은 전부 잃어버린다.

length 프로퍼티를 현재의 값보다 크게 설정하면 배열의 끝부분에 정의되지 않은 원소들이 추가되면서 배열이 새로운길이로 늘어난다.

7.6.6 다차원 배열 구구단 예

var table = new Array(10);for(var i = 0; i < table.length; ++i) table[i] = new Array(10);

for(var r = 0; r < table.length; ++r) {for(var c = 0; c < table[r].length; ++c) {

table[r][c] = r * c;}

}

7.7 배열 메서드join() ⇒ 모든 원소를 문자열로 변환하고 이어 붙여서 반환한다. 전달인자를 넘겨 구분자 문자열을

지정할 수 있다. ‘기본값 ,’ 반대 기능 split() ⇒ 문자열을 조각들로 분리하고 이 조각들을 원소로 하는 배열을 생성

reverse() ⇒ 배열 안의 원소 순서를 반대로 정렬하여 반환한다. 이미 존재하는 배열 안에서 원소들의 순서를 뒤바꾼다.

sort();var a = [33, 5, 111, 222];a.sort();a.sort(function(a,b) { return a-b; });

concat(); // ???

var a = [1,2,3];a.concat(4, 5) // [1,2,3,4,5]a.concat([4,5]) // [1,2,3,4,5]a.concat([4,5], [6,7]); // [1,2,3,4,5,6,7]a.concat([4, [5, [6,7]]); // [1,2,3,4,5,[6,7]]

slice(); / ???

var a = [1,2,3,4,5];a.slice(0,3); // [1,2,3]

Page 11: Javascript 완벽 가이드 정리

a.slice(3); // [4,5]a.slice(1,-1); // [2,3,4]a.slice(-3,-2); // [3] ???

splice()

var a = [1,2,3,4,5,6,7,8];a.splice(4); // [5,6,7,8] 을 반환한다. a = [1,2,3,4]a.splice(1,2); // [2,3] 을 반환한다. a = [1,2];a.splice(1,1); // [4] 를 반환한다. a = [1]

var a = [1,2,3,4,5];a.splice(2,0, ‘a’, ‘b’); // [] 를 반환한다. a 는 이제 [1,2,’a’, ‘b’, 3, 4, 5]a.splice(2,2,[1,2],3); // [‘a’, ‘b’] 를 반환한다. a 는 이제 [1,2,[1,2],3,3,4,5]

push(), pop()unshift(), shift()toString(), toLocaleString()

indexOf(), lastIndexOf();forEach();map();filter();

8 장 함수

자바스크립트에서 함수는 다른 함수 안에 중첩되어 정의될 수 있다.function hypotenuse(a, b) {

function square(x) { return x * x; }return Math.sqrt(square(a) + square(b));

}

중첩된 함수는 최상위 레벨에서만 정의할 수 있음 즉 if, while 루푸의몸체 같은 문장 블록 안에서는 정의할 수 없다. 함수 리터럴은 어디에든 위치할 수 있다.

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

var f = function fact(x) { if(x <= 1) return 1;else return x * fact(x-1);

}

이름 없는 함수를 생성하고 이 함수에 대한 참조를 변수 f 에 저장한다. 함수에 대한 참조를 fact 변수에 저장하지는 않지만 함수의 몸체 안에서 자신을 참조하기 위해 이 이름을 사용하는 것은 허용한다.

Page 12: Javascript 완벽 가이드 정리

f[0] = function(x) { return x * x; };a.sort(function(a,b) { return a-b; });var tensquared = (function(x) { return x * x; })(10);

전달인자의 개수보다 적은 수의 전달인자와 함께 호출되면, 지정되지 않은 전달인자는 undefined 가된다.

a = a || []; // good !

자바스크립트 함수는 비록 고정된 개수의 이름 붙은 전달인자들로 정의되지만 호출 시점에서는 이 고정된 개수와는 상관없이 임의 개수의 전달인자들을건네받을 수 있다. Arguments 객체는 이름이

붙어있든 없든 상관없이 건네받은 모든 전달인자의 값에 접근하기 위한 방법을 제공한다.

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,1000,6);

만약 함수에 이름 붙은 전달인자가 있으면 Arguments 객체의 배열 원소는 함수 전달인자를 담은 지역 변수의 별칭이 된다. arguments[] 배열과 이름 붙은 전달인자는 동일한 변수를 참조하는 두 가지 다른

방법이다. 전달인자 이름을 사용하여 전달인자의 값을 변경하면 arguments[] 배열을 통해 읽어 들이는 값도 변한다.

function f(x) {print(x);arguments[0] = null;print(x);

}

calee 프로퍼티⇒ 현재 실행되고 있는 함수를 가리키는 calee 프로퍼티를 추가로 정의한다. 이름 없는 함수도 자기 자신을 재귀적으로 호출할 수 있다.

function(x) {if(x <= 1) return 1;return x * arguments.callee(x-1);

}

function(x) {console.log(arguments.calee); // ????

}

Page 13: Javascript 완벽 가이드 정리

8.2.3 객체 프로퍼티를 전달인자로 사용하기

function easycopy(args) {arraycopy(args.from, args.from_start || 0, args.to, args.to_start || 0, args.length);

}var a = [1,2,3,4];var b = new Array(4);easycopy({from:a, to:b, length:4});

// 튼튼한 함수 만들기 예

function sum(a) {if( (a instanceOf Array) || (a && typeof a == “object” && “length” in a)) { var total = 0;

for(var i = 0; i < a.length; ++i) {var element = a[i];if(!element) continue;if(typeof element == “number”) total += element;else throw new Error(“sum(); 모든 배열 원소는 숫자이어야 함.”);

} return total;} else { throw new Error(“sum(): 전달인자는 반드시 배열이어야 함.”);}

}

자바스크립트는 매우 유연하고 또 데이타 타입 제약이 느슨한 언어라서 때로는 함수가 건네받은 전달인자들의 개수와 데이터 타입에 유연하게 대처 할 수 있는 함수를 작성하는 것이 적절할 수 있음.

예.

function flexisum(a) {var total = 0;for(var i = 0; i < arguments.length; ++i){

var element = arguments[i];if(!element) continue;

var n;switch(typeof element) {case “number”:

n = element;

Page 14: Javascript 완벽 가이드 정리

break;case “object”:

if( element instanceOf Array) {n = flexisum.apply(this, element);

} else {n = element.valueOf();

}break;

case “function”:n = element();break;

case “string”:n = parseFloat(element);break;

case “boolean”:n = NaN;break;

}

if(typeof n == “number” && !isNaN(n)) total += n;else throw new Error(“sum(): “ + element + “ 을 숫자로 변환하는데 실패.”);

}

return total;}

8.3 데이타로서의 함수

8.4 메서드로서의 함수

호출된 메서드가 속하여 있는 객체는 메서드 몸체 안에 this 라는 키워드의 값으로 저장된다. var calculator = {

operand1: 1,operand2: 1,cumpute: function() {

this.result = this.operand1 + this.operand2;}

};

calculator.compute();print(calculator.result);

Page 15: Javascript 완벽 가이드 정리

8.6 함수 프로퍼티와 메서드length 프로퍼티 함수가 건네받기를 기대하는 전달인자의 개수를 반환한다.

function check(args) {args.calee.length;

}

8.6.2 prototype 프로퍼티

8.6.3 나만의 함수 프로퍼티 정의하기 전역변수에 저장할 수 있으나 한 함수에서만 사용되는 정보를 전역으로 정의하는 것은 불필요한 작업. 이

경우에는 정보를 Function 객체의 프로퍼티에 저장하는 것이 더 좋다.

uniqueInteger.counter = 0;

function uniqueInteger() {return uniqueInteger.counter++;

}

apply(), call() // ????

f.call(o, 1,2) ⇒o.m = f;o.m(1,2);delete o.m;

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

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

8.7 유용한 함수들

8.8.4   클로저로서의 중첩된 함수

자바스크립트 함수는 실행될 코드와 이 함수가 실행될 유효 범위의 조합이다. 컴퓨터 과학문헌에서 이러한 코드와 유효 범위의 조합은 클로저(closure) 로 알려져 있다. 모든 자바스크립트 함수는 클로저다.

이 클로저가 유일하게 흥미로운 경우는 바로 위에서 설명했듯이 중첩된 함수가 그 함수가 정의된 유효 범위의 바깥으로 익스포트(export) 될 때다.

uniqueID = (function() {var id = 0;return function() { return ++id; }

Page 16: Javascript 완벽 가이드 정리

});

var id = uniqueID(); // good !!

function makeProperty(o, name,predicate) {var value;o[“get” + name] = function() { return value; }o[“set” + name] = function(v) {

if(predicate && !predicate(v)) {throw “set” + name + “: invalid value “ + v;

} else {value = v;

}};

}

////var o = {};makeProperty(o, “Name”, function(x) { return typeof x == “string”; });o.setName(“Frank”);console.log(o.getName());o.setName(0);

8.9 Function() 생성자

var f = new Function(“x”, “y”, “return x*y”);

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

var y = “global”;function constructFunction() {

var y = “local”;return new Function(“return y”);

}console.log(constructFunction()()); // “global”

9.1 생성자

new 연산자와 함께사용되도록 설계된 함수를 생성자 함수라고 하거나 간단히 생성자라 한다.

Page 17: Javascript 완벽 가이드 정리

생성자 함수에서 결과값으로 객체를 반환하면 반환값을 가질 수 있으며, 이때 반환되는 객체는 new 문장의 결과값이 된다. 그리고 생성자 안의 this 가 가리키고 있던 객체는 폐기된다.

function Rectangle(w, h) {this.width = w;this.height = h;this.area = function() { return this.width * this.height; }

}

var rect = new Rectangle(10,10);

prototype 의 이해

function Rectangle(w, h) {this.width = w;this.height = h;

}

Rectangle.prototype.area = function() { return this.width * this.height };

이 생성자를 통해 생성되는 객체들은 프로토타입이 가진 프로퍼티들을똑같이 상속받는다. 이 말은 프로토타입 객체가 메소드나 상수 같은 프로퍼티들을 위치시키기에 좋은 곳임을 의미한다.

프로토타입 객체를 사용하면 각 객체가 프로토타입의 프로퍼티를 상속받기 때문에 이들이 필요로 하는 메모리의 양을 상딩히 줄일 수 있다. 프로토타입에 새로운 프로퍼티가 추가되면, 이미 생성되었던

객체일지라도추가된 프로퍼티를 그대로 상속받는다.

프로퍼티의 상속은 프로퍼티를 쓸때가 아닌 읽을 때만 일어난다 ???

9.2.2 내장형 타입의확장

String.prototype.endsWidth = function(c) {return (c == this.charAt(this.length-1);)

}

인스턴스 프로퍼티 인스턴스 메서드

클래스 프로퍼티 클래스 메서드

Circle 클래스

function Circle(radius) {this.r = radius;

Page 18: Javascript 완벽 가이드 정리

}

Circle.PI = 3.14159;Circle.prototype.area = function() { return Circle.PI * this.r * this.r; }Circle.max = function(a, b) {

if(a.r > b.r) return a;else return b;

}

var c = new Circle(1.0);c.r = 2.2;var a = c.area();var x = Math.exp(Circle.PI);var d = new Circle(1.2);var bigger = Circle.max(c,d);

9.3.7 private 멤버

자바스크립트는 클로저를 사용하여 흉내낼 수 있지만 이를 위해서는 인스턴스 마다 접근 메서드가 저장되어 있어야 한다. 이들은 프로토타입 객체에서 상속받지 못한다.

function ImmutableRectangle(w, h) {this.getWidth = function() { return w; }this.getHeight = function() { return y; }

}

ImmutableRectangle.prototype.area = function() {return this.getWidth() * this.getHeight();

}

http:///www.crockford.com/javascript/private.html

toString() 메서드

toString() 을 사용해 변환한 문자열을 다시 객체 형태로 바꾸기 위해 static parse() 메서드를 추가하는 것도 고려할 수 있겠다.

여러분이 만든 클래스의 인스턴스들이 서로 동등한지검사할 수 있게 하려면 equal() 라는 인스턴스 메서드를 정의하라. 여러분이 원하는 순서대로 객체를 비교하기 위해서는 compareTo() 메서드를 사용할 수 있다.

inst.sort(function(a,b) { return a.compareTo(b); });

Page 19: Javascript 완벽 가이드 정리

9.5 수퍼 클래스와 서브클래스

function Rectangle(w, h) {this.width = w;this.height = h;

}Rectangle.prototype.area = function() { returh this.width * this.height; }

function PositionedRectangle(x, y, w, h) {// 초기화될 객체의 매서드로 생성자를 호출할 수 있게 call() 메서드를 사용한다.// 이 기법은 생성자 체이닝( chaining) 이라고 불린다.Rectangle.call(this, w, h);

this.x = x;this.y = y;

}

// Rectangle 을 서브클래스화 시키려면 명시적으로 프로토타입 객체를 생성해야 한다.PositionedRectangle.prototype = new Rectangle();

delete PositionedRectangle.prototype.width; // ????delete PositionedRectangle.prototype.height; // ????

PositionedRectangle.prototype.constructor = PositionedRectangle;

PositionedRectangle.prototype.contains = function(x, y) {return (x > this.x && x < this.x + this.width &&

y > this.y && y < this.y + this.height);}

9.5.1 생성자 체이닝

생성자 함수는 상위 클래스의 생성자 함수를 명시적으로 호출해야 했었다. 이런 작업을 생성자 체이닝이라고 부르며 하위 클래스를 생성할때 굉장히 자주 사용된다. 하위 클래스의 프로토타입 객체에

superclass 라는 프로퍼티를 추가하는 방법을통해 생성자 체이닝을 위한 문법 간소화

PositionedRectangle.prototype.superclass = Rectangle;

function PositionedRectangle(x, y, w, h) {this.superclass(w,h);this.x = x;this.y = y;

}

Page 20: Javascript 완벽 가이드 정리

9.5.2 재정의된 메서드 호출하기

PositionedRectangle.prototype.toString = function() {return “(“ + this.x + “,” + this.y + “)” +

Rectangle.prototype.toString.apply(this); // 상위 클래스에 체이닝// this.superclass.prototype.toString.apply(this);

}

9.6 상속없이 확장하기

빌려주는 작업을 수행할 목적으로 만들어진 클래스를믹스인(mixin) 클래스 혹인 믹스인 이라고 부른다.

function borrowMethods(borrowFrom, addTo) {var from = borrowFrom.prototype;var to = addTo.prototype;

for(m in from) {if(typeof from[m] != “function”) continue;to[m] = from[m];

}}

function GenericToString() {}GenericToString.prototype.toString = function() {…}

borrowMethods(GenericToString, Rectangle);

function Colored(c) { this.color = c; }Colored.prototype.getColor = function() { return this.color; }

function ColoredRectangle(x, y, w, h, c) {this.superclass(x,y,w,h);Colored.call(this,c);

}

ColoredRectangle.prototype = new Rectangle();ColoredRectangle.prototype.constructor = ColoredRectangle;ColoredRectangle.prototype.superclass = Rectangle;

borrowMethods(Colored, ColoredRectangle);

Page 21: Javascript 완벽 가이드 정리

9.7.1 instanceof 와 constructor

var d = new Date();var isobject = d instanceof Object; // truevar realobject = d.constructor == Object; // false

9.7.3 오리 타이핑

10 장 모듈과 네임스페이스

JSAN ( 자바스크립트 Archive Network)http://www.openjsan.org

전역 변수를 정의하 말라.

var Class = {};Class.define = function(data) { .. }Class.provides = function(o,c) { … }