var empty = [];
var primes = [2,3,5,7,11];
var misc = [ 1.1, true, "a" ];
// 임의의 표현식도 사용 가능
var base = 1024;
var table = [base, base+1, base+2, base+3];
var count = [1,,3]; // 가운데 값은 undefined
var undefs = [,,]; // 원소는 2개 (마지막원소에 , 가능)
Array 생성자
var a = new Array();
var aa = new Array(10); // length
var aaa = new Array(5,4,3,2,1, "testing, testing"); // 인자값이 배열의 원소
console.log(aaa)
배열에 속한 원소의 위치가 연속적이지 않은 배열 원소가 undefined가 아니라 아예 없는 것
arr = new Array(5); // 원소는 없지만 a.length의 값은 5
arr2 = [] // length값이 0인 빈 배열
arr3[1000] = 1; // 하나의 원소 할당, 길이는 1000
배열의 길이
배열의 length Property : 배열의 원소 개수, 배열의 가장 큰 인덱스+1
length 값 변경 :
a = [1,2,3,4,5];
a.length = 3; // 결과가 1,2,3이 된다.
a.length = 0; // 결과 []
a.length = 5; // new Array(5)와 같은 결과
length Property 읽기전용으로 만들기 :
a = [1,2,3];
Object.defineProperty(a, "length", {writeable: false});
a.length = 0; // 값 바꿔도 배열은 변하지 않음
배열 원소 추가 제거
a = [];
a[0] = "zero";
a.push("one");
a.push("two", "three");
console.log(a.length);
delete a[1];
console.log(1 in a); // false -> 지워졌다.
console.log(a.length);
Output :
배열 순회하기
var o = new Array(7,5,3,2);
var keys = Object.keys(o);
var values = [];
for(var i = 0; i < keys.length; i++) {
var key = keys[i];
values[i] = o[key];
}
console.log(o);
console.log(keys);
console.log(values);
for(var i = 0, len = keys.length; i < len; ++i) {
// 성능향상 위해 length를 한번만 불러오기
}
Output :
루프 돌릴 때 고려해야 할 점
원소가 null / undefined 일 때 어떻게 처리할 지
상속받은 Property 등의 고유 Property 가 아닌 값들을 어떻게 처리할 지
for in loop에서 원소 반환 순서
정해져있지 않음.
순서가 중요한 알고리즘에서는 for문을 통해 명시적으로 사용할 것을 권장
다차원 배열
var table = new Array(10);
for(var i = 0; i < table.length; ++i) {
table[i] = new Array(10);
}
for(var i = 0; i < table.length; ++i) {
for(var j = 0; j < table[i].length; ++j) {
table[i][j] = i*j;
}
}
console.log(table[5][7]);
Output :
배열 메서드
join()
* 배열의 모든 원소를 문자열로 변환, 변환한 문자를 이어붙인 결과를 return
* seperator를 지정하지않으면 , 가 기본 separator
* String.split() -> join의 반대. 문자열을 배열로
var a = [1, 2, 3];
console.log(a.join());
console.log(a.join(' '));
console.log(a.join(''));
Output :
reverse()
배열의 원소 순서를 반대로 뒤집어 반환.
배열안에서 직접 수행되어 배열 정렬순서 변환됨.
var b = [1,2,3];
b.reverse();
console.log(b);
Output :
sort()
정렬
undefined는 배열의 끝부분으로
정렬 조건도 바꿀 수 있음
var c = [1,2,3,4];
c.sort();
console.log(c);
c.sort(function(a,b) {
return b - a;
})
console.log(c);
Output :
concat()
concat의 전달인자를 추가한 배열 반환
var d = [1,2,3];
console.log(d.concat(4,5));
console.log(d.concat([4,5]));
console.log(d.concat([4,5], [6,7]));
console.log(d.concat([4, [5,6]]));
Output :
slice()
subarray 반환
-1은 마지막 원소
음수는 뒤에서부터 세는 것
var e = [1,2,3,4,5];
console.log(e.slice(0,3));
console.log(e.slice(3));
console.log(e.slice(1,-1));
console.log(e.slice(-3,-2));
temp.newProperty : 식별자가 와야 함 -> 코딩할 때 fix됨. temp.["new Property"] : 표현식을 인자로 받음 -> 프로그램 실행중 입력받은 것 사용 가능
function addName(nameList, name, studentNumber) {
nameList["name"] = studentNumber
}
// 이런 코드가 동작 한다는 뜻!
상속
객체에서 Property를 찾을 때, 고유 Property안에 찾고자 하는 Property가 없으면, 상속받은 Prototype 객체에서 해당 Property를 찾는다.
function inherit(p) {
if (p == null) throw TypeError();
if (Object.create) // ECMAScript 5 이상에 정의되어 있음
return Object.create(p);
}
var o = {};
o.x = 1;
var p = inherit(o); // 객체 o와 Object.prototype를 상속받는 객체
p.y = 2;
var q = inherit(p); // 객체 p와 o, Object.prototype을 상속받는 객체.
q.z = 3;
var s = q.toString(); // q 는 Object.prototype을 상속받았기 때문에 toString 사용가능
var result = q.x + q.y; // 값은 3
console.log(result);
Output :
상속받은 Prototype Property를 바꾸고 싶을 때
상속받은 Property 가 read only 라면 수정 불가. 그렇지 않다면 두 가지 경우의 수
고유 Property로 재정의 된다. // 기본
Prototype Property 의 값이 재설정된다. // setter method가 정의되어있을 경우
Property 접근 에러
존재하지 않는 Property에 접근하는 경우
에러 발생하지 않음. -> undefined return
존재하지 않는 객체의 Property에 접근하는 경우
에러 발생
var temp2 = o.a;
console.log(temp2) // undefined
var length = o.a.length; // undefined에서 Property를 찾으려 해서 error
Output :
에러 방지
var len = temp2 && temp2.a && temp2.length
객체 o에 Property p를 설정할 수 없는 경우
p가 o의 고유 Property이고 readonly일 경우
읽기전용 Property p 에는 값 설정할 수 없다.
p가 상속된 Property 이고 readonly일 경우
동일한 이름의 고유 Property로 감출 수 없음.
p가 고유 Property도, 상속받은 Property도 아닌데 extensible 속성이 false일 경우.
프로퍼티 삭제하기
delete 연산자. Property의 값이 아니라 Property 자체를 지움
delete book.author;
delete book["main title"];
delete 연산자는
고유 프로퍼티만 지울 수 있다.
삭제에 성공, 프로퍼티가 존재하지 않아 영향을 미치지 못한 경우, return true를 한다.
o = {x:1}
delete o.x; // 삭제 성공 return true
delete o.x; // 존재하지 않아 return true
delete o.toString; // 고유프로퍼티가 아니라 아무일도 안일어나고 true
delete 1; // 말도 안 되지만 return true
* configurable 속성이 false 인 프로퍼티는 지우지 않는다.
아래는 nonreconfigurable
delete Object.prototype; // 지울 수 없음
var x = 1;
delete this.x; // 지울 수 없음
function f() {}
delete this.f; // 지울 수 없음
var oo = {x : 1};
console.log("x" in oo);
console.log("y" in oo);
console.log("toString" in oo);
console.log(oo.hasOwnProperty("x"));
console.log(oo.hasOwnProperty("y"));
console.log(oo.hasOwnProperty("toString"));
var ooo = inherit({y : 2});
ooo.x = 1;
console.log(ooo.propertyIsEnumerable("x")); // 고유 프로퍼티 열거 가능 -> true
console.log(ooo.propertyIsEnumerable("y")); // 상속받은 프로퍼티 -> false
console.log(ooo.propertyIsEnumerable("toString")); // 내장프로퍼티, 열거불가능 -> false
Output:
!== 와 === 연산자
undefined 와 null 을 구분할 수 있음.
프로퍼티 열거하기
for / in loop
var o = {x:1, y:2, z:3};
for(p in o) {
console.log(p, o[p]);
}
Output :
상속받은 Property 생략, method 생략
for(p in o) {
if(!o.hasOwnProperty(p))
continue;
}
for(p in o) {
if(typeof o[p] === "function")
continue;
}
프로퍼티 Getter / Setter
ECMAScript 5 에서는 Property의 값을 getter / setter method로 대체할 수 있음. 단순히 값을 값는 "Data Property" 와 다른 "Accessor Property" 라고 한다.
프로그램이 객체의 Accessor Property에 접근하면 getter method의 반환 값이 Property 접근 표현식의 값이 됨.
프로그램이 객체의 Accessor Property의 값을 바꾸려고 하면 getter method가 실행된다. = 오른쪽의 값이 method의 인자로 전달된다.
getter / setter 존재 유무로 읽기전용, 쓰기전용 결정. 특이한 것 : setter 만 있으면 쓰기전용. read 하려고 하면 있음에도 undefined return
Accessor Property의 정의
var oo = {
// Data Property
data_prop: value,
get accessor_prop() { /* 함수 몸체 */},
set accessor_prop(value) { /* 함수 몸체 */ }
}
Example : 2차원 좌표와 극좌표를 가지는 Property
var p = {
x: 1.0,
y: 1.0,
get r() {
return Math.sqrt(this.x*this.x + this.y*this.y);
},
set r(newValue) {
console.log("in setter : ", newValue);
var oldValue = Math.sqrt(this.x*this.x + this.y*this.y);
var ratio = newValue / oldValue;
this.x *= ratio;
this.y *= ratio;
console.log("now x : ", this.x);
console.log("now y : ", this.y);
},
get theta() {
return Math.atan2(this.y, this.x);
}
}
var q = inherit(p);
q.x = 1; q.y = 1;
console.log(q.r);
console.log(q.theta);
q.r = 777
console.log(q.r);
console.log(q.theta);
Output
Example : 일련번호 생성
var serialnum = {
$n: 0, // 프로퍼티 이름의 $는 private 프로퍼티라는 힌트
get next() {return this.$n++;},
set next(n) {
if(n>=this.$n) this.$n++;
else throw "serial number can only be set to a larger value";
}
}
Property 속성
이름, 값, 그리고 속성
value
데이터 프로퍼티의 값도 속성으로 본다.
writeable
값 변경 가능 여부
enumerable
열거가능 여부
configurable
3가지 속성 변경 가능한지.
Property의 3가지 속성 값을 질의하고 설정할 수 있도록 하는 ECMAScript 5 API
라이브러리 만들 때 중요
프로토타입 객체에 method 추가 , 추가된 method를 내장 method처럼 열거할 수 없게 만들기 위해
변경, 삭제 불가한 프로퍼티를 정의, 객체를 고정(lock down) 시키기 위해
접근자 Property의 속성 표현 위해 Property descriptor라는 객체 사용.
데이터 Property의 Property descriptor
value, writeable, enumerable, configurable 등의 Property를 가짐
접근자 Property의 Property descriptor
get, set, enumerable, configurable
객체의 특정 Property에 대한 Property descriptor객체 -> Object.getOwnPropertyDescriptor() 를 통해 얻을 수 있음.
console.log(Object.getOwnPropertyDescriptor({x:1}, "x"));
// 없는 Property거나 상속받은 Property 는 undefined
console.log(Object.getOwnPropertyDescriptor({}, "x"));
console.log(Object.getOwnPropertyDescriptor({}, "toString"));
Output
getOwnPropertyDescriptor 는 고유 프로퍼티만 검사 가능. 상속된 프로퍼티를 검사하고 싶으면 프로토타입 chain을 명시적으로 순회해야함.