객체는 이름과 값을 한 쌍으로 묶은 데이터를 여러 개 모은 것이빈다. 즉, 객체는 여러개를 하나로 모은 복합 데이터로 연관 배열 또는 사전이라고도 부릅니다.
| 이름 | 값 |
|---|---|
| suit | "하트" |
| rank | "A" |
이름과 값의 쌍을 가리켜 우리는 객체의 property라고 부릅니다. suit와 rank는 property의 이름(key), "하트", "A"를 우리는 값(value)이라고 부릅니다.
다음 코드는 트럼프 카드의 정보를 객체 리터럴로 표현한 것입니다.
var card = { suit: "하트", rank: "A" };
{...} 부분이 바로 객체 리터럴입니다. 객체 리터럴을 변수 card에 대입하고있습니다. 프로퍼티의 이름과 프로퍼티의 값을 우리는 콜론(:) 으로 구분합니다. 또한 중괄호 안에 있는 여러개의 프로퍼티들을 구분하기 위하여 우리는 쉼표(,)를 사용합니다. 프로퍼티의 이름으로는 모든 식별자, 문자열 리터럴(빈 문자열도 가능)을 사용할 수 있습니다. 즉, 앞 코드에 있는 프로퍼티의 이름은 문자열로 바꾸어 작성이 가능합니다.
또한 변수에 대입된 객체 안의 프로퍼티 값을 읽거나 쓸 떄는 마침표(.) 연산자, 대괄호([]) 연산자를 사용하면 됩니다.
card.suit // => 하트
card["rank"] // => A
card.number // undeifined (객체에 없는 property)
마침표(.)연산자를 사용하여 프로퍼티를 읽거나 쓸 떄는 프로퍼티의 이름 즉, 식별자만 사용이 가능합니다.
대괄호([])로 프로퍼티를 읽거나 쓸 떄는 프로퍼티의 이름, 문자열을 반환하는 표현식을 사용할 수 있다.
위의 card.number 처럼 없는 프로퍼티를 읽을려면 undefined를 반환합니다.
var obj = {}
console.log(obj): // => Object{}
객체 리터럴안에 프로퍼티를 작성하지않으면 빈 Object가 생성됩니다.
없는 프로퍼티에 이름과 값을 대입하면 새로운 프로퍼티가 추가됩니다.
card.value = 7;
console.log(card); // -> Object {suit: "하트", rank: "A", value: 14}
delete card.rank
console.log(card); // Object {suit: "하트", value: 14}
JS의 객체는 자유롭게 실행 중에 프로퍼티를 추가하거나 삭제할 수 있습니다. 하지만, Java C++ 등에서는 불가능합니다.
in 연산자를 활용하면 객체에 특정 프로퍼티가 있는지 여부를 확인할 수 있다.
var card = { suit: "하트", rank: "A" };
console.log("suit" in card); // true
console.log("color" in card); // false
아래와 같이 작성해서 사용하면 됩니다.
프로퍼티의 이름을 뜻하는 문자열 in 객체명
객체 리터럴을 사용하는 몇 가지 예를 살펴보겠습니다.
var p = { x: 1.0, y: 2.5 };
var circle = {
center: { x : 1.0, y : 2.0 }, // 원의 중점을 표현하는 객체
radius: 2.5 // 원의 반지름
};
center 프로퍼티는 원의 중점을 표현, radius 프로퍼티는 원의 반지름을 표현합니다.
circle.center.x // -> 1.0
위와 같이 원 중점의 x좌표를 표현할 수 있습니다.
var person = {
name: "김용민",
age: 24,
sex: "male"
married: false
};
프로퍼티에 저장된 값의 타입이 함수면 그 프로퍼티를 메서드라고 부릅니다.
생성된 객체는 메모리의 영역을 차지하는 한 덩어리가 된다. 객체 타입의 값을 변수에 대입하면 그 변수에는 객체의 참조(메모리에서의 위치 정보)가 저장됩니다. 이떄의 변수 상태를 가리켜 그 객체를 참조하고 있다라고 합니다.

위의 그림은 변수 card에 트럼프 카드 객체의 참조(위치 정보)가 저장되어 있습니다. 변수에 저장된 객체의 참조는 다른 원시 값과 마찬가지로 다른 변수에 저장할 수 있습니다.
var card2 = card;
그러면 변수 card2가 card 객체를 참조하게 되므로 card2로 card의 객체를 읽거나 수정할 수 있습니다.
console.log(a.suit); // 하트
a.suit = "스페이드"
console.log(a.suit); // 스페이드
console.log(card.suit); // 스페이드

수학에서는 함수의 주어진 입력 값 x에 대해 출력 값 y를 대응시키는 규칙입니다.
함수 이름을 f라 할떄 함수 값인 y는 우리는 흔히 f(x)라고 수학시간떄 다들 배웠습니다.
자바스크립트에서의 함수는 일련의 처리를 하나로 모아서 언제든 호출할 수 있도록 편의상 만들어놓은 것이라고 생각하면됩니다.
입력 값을 받으면 출력 값으로 함수 값을 반환합니다.
수학 함수와 다른 점은 입력을 받은 후에 함수 안의 프로그램에서 특정 작업을 수행한다는 점 입니다.
JS에서 함수의 입력값을 인수라고 부르고, 함수의 출력 값을 반환값이라고 부릅니다.
함수는 function 키워드를 사용해서 정의합니다. 예를 들어 다음은 square 함수를 정의하는 코드입니다. square는 제곱이란 의미이다.
function square(x) { return x * x; }
{ } 중괄호 안에 있는 코드가 함수를 실행하는 작업입니다. 앞 코드에서 함수가 처리하는 내용은 다음의 return 문 뿐입니다.
return x * x;
return문을 실행하면 제어권이 함수를 호출한 코드로 되돌아가고, return 문에 지정된 값(앞 코드에서는 x * x: x와 x의 곱)은 함수의 반환값이 됩니다.
변수 이름과 마찬가지로 이름을 지으면 됩니다. 하지만 함수의 이름은 그 함수가 실행하는 기능을 이해할 수 있도록 쉽게 이름을 작성해야합니다. (코드 이해(가독성), 유지 보수성)
함수를 호출하려면 함수 이름 뒤에 소괄호를 인수로 묶어 입력합니다.
square(3);
함수는 인수를 여러 개 받을 수 있습니다. 인수가 여러 개라면 인수와 인수를 쉼표(,)로 구분합니다.
function dist(p, q) {
var dx = q.x - p.x;
var dy = q.y - p.y;
return Math.sqrt(dx*dx+dy*dy);
}
이 코드에 등장하는 Math.sqrt는 제곱근을 구하는 함수입니다. 함수 dist를 사용하여 두 점 사이의 거리를 구하는 코드는 다음과 같습니다.
var p1 = {x:1, y:1};
var p2 = {x:4, y:5};
var d = dist(p1, p2);
인수를 받지 않는 함수도 정의가 가능합니다.
var bark = function { console.log("bow-wow"); };
bark(); // "Bow-bow"
함수의 실행흐름
1. 호출한 코드에 있는 인수가 함수 정의문 인자에 대입됩니다.
2. 함수 정의문의 중괄호 안에 작성된 프로그램이 순차적으로 실행된다.
3. return 문이 실행되면 호출한 코드로 돌아간다. return 문의 값은 함수의 반환값이 된다.
4. return 문이 실행되지 않은 상태로 마지막 문장이 실행되면, 호출한 코드로 돌아간 후에 undefined가 함수의 반환값이 된다.
console.log(square(5));; // -> 25
function square(x) { return x * x; }
변수 선언문과 마찬가지로 함수 선언문을 프로그램의 첫 머리로 끌어올립니다.
함수를 정의하기 전에 실행하는 코드를 작성해도 출력하는데 문제가 발생하지 않습니다.
자바스크립트에서는 함수가 객체이다. 함수 선언문으로 함수를 선언하면 내부적으로 그 함수 이름을 변수 이름으로 한 변수와 함수 객체가 만들어집니다. 그 변수에 함수 객체의 참조가 저장됩니다. 아래 그림을 확인해 봅시다.

var sq = square;
console.log(sq(5)); // -> 25
// 함수를 다른 함수의 인수로 넘길 수도 있다.
함수는 원시 값을 인수로 넘겼을 때 객체를 인수로 넘겼을 때 다르게 동작합니다. 먼저 인수가 원시 값일 때 어떻게 동작하는지 예제를 살펴보겠습니다.
function add1(x) { return x = x + 1; }
var a = 3;
var b = add1(a);
console.log("a = " + a + ", b = " + b); // a=3, b=4
add1은 전달받은 인수에 1을 더하여 반환하는 함수입니다. 이 함수가 호출될 때 변수 a의 복사본이 인자 x에 할당됩니다. 즉, 인수에 원시 값을 넘기면 그 값 자체가 인자에 전달됩니다.
이를 가리켜 값의 전달이라고 부릅니다. 이때 변수 a와 변수 x는 다른 영역의 메모리에 위치한 별개의 변수입니다. 따라서 x값을 바꾸더라도 a값은 바뀌지 않습니다.

다음으로 인수가 객체일 떄 어떻게 동작하는지 예제를 살펴보겠습니다.
function add1(p) { p.x = p.x + 1; p.y = p.y + 1; return p; }
var a = { x:3, y:4 };
var b = add1(a);
console.log(a, b); // -> Object {x=4, y=5}
이번에 등장한 add1 함수는 2차원 좌표의 각 성분에 1을 더한 좌표를 반환하는 함수입니다. 함수가 호출될 떄 변수 a의 복사본이 인자 p에 할당됩니다. 여기까지는 원시 값을 인수로 넘겼을 떄와 동일하게 동작합니다.
그러나 이전과 다르게 변수 a에 객체 {x:3, y:4}의 참조가 저장되어 있으며, 이 참조 값을 인자 p에 대입합니다.
즉, 인수를 객체로 넘겼을 때 전달되는 값은 참조 값입니다. 이를 가리켜 참조 전달이라고 부릅니다. 이때 인자 p와 변수 a는 똑같은 객체를 참조하고 있습니다. 따라서 함수 안에서 p.x와 p.y를 수정하는 행위는 a.x와 a.y를 수정하는 행위와 같습니다. 이처럼 함수의 인수로 객체를 넘기면 함수 안에서 원래의 객체를 바꿀 수 있습니다.

함수에 넘겨야 하는 인수 개수가 많아지면 다음과 같은 문제가 발생합니다.
1. 함수 순서 착각
2. 함수가 받는 인수 개수를 바꾸면 함수의 호출 방법이 바뀌므로 프로그램 전체를 수정해야합니다.
객체의 프로퍼티에 인수를 담아서 넘기면 이러한 문제를 우아하게 해결할 수 있다.
다음과 같이 인수가 많은 함수를 예로 들어보자.
function setBallProperties(x, y, vx, vy, radius) {...}
...
setBallProperties(0, 0, 10, 15, 5);
// 이 함수의 인수를 아래같이 객체의 프로퍼티에 담아서 함수에 넘기자!
// 이렇게 수정하면 함수의 인수를 하나만 받도록 만들 수 있습니다.
// 이떄 함수 안에서 properties를 읽는 코드는 params.x 처럼 표현하면 되고, 인수 순서가 바뀌는 문제가 발생하지 않습니다.
var parameters = {
x: 0,
y: 0,
vx: 10,
vy: 15,
radius: 5
};
// 인수를 추가하는 경우에는 프로퍼티만 추가하면 됩니다. 함수를 호출하는 방법은 변경할 필요가 없습니다.
var parameters = {
x: 0,
y: 0,
vx: 10,
vy: 15,
radius: 5,
color: "blue"
};
setBallProperties(parameters);
// 단, 함수 안에서 객체의 프로퍼티를 수정하면 호출한 코드에 있는 인수 객체의 프로퍼티가 함께 바뀌므로 주의해야합니다. 객체를 인수로 넘기면 함수에는 객체의 참조가 전달되기 때문이다.
변수에 접근할 수 있는 범위를 그 변수의 유효 범위(scope)라고 합니다. 두가지의 종류가 있는데 하나는 프로그램의 구문만으로 유효 범위를 정하는 lexical scope(어휘적 범위), 프로그램 실행 중에 유효 범위를 정하는 dynamic scope(동적 범위)입니다.
C/Java/JS도 lexical scope를 사용합니다. 자바스크립트의 변수는 변수의 유효 범위에 따라 두가지로 나뉘게 됩니다. 하나는 전역변수, 다른 하나는 지역변수입니다.
전역 변수는 함수 바깥에서 선언된 변수로 유효 범위가 전체 프로그램입니다. 지역 변수는 함수 안에서 선언된 변수와 함수 인자로 유효 범위는 변수가 선언된 함수 내부입니다. 예를 들면 다음과 같습니다.
var a = "global"; // => 전역 변수
function f() {
var b = "local"; // b의 유효 범위;
console.log(a); // -> "global"
return b;
}
f();
console.log(b); // ReferenceError : b is not defined
변수 a는 전역변수입니다. 전역 변수의 유효 범이ㅜ는 프로그램 전체입니다. 즉, 변수 a는 함수 내부에서도 유효하게 사용할 수 있습니다. 다만 변수 b는 함수 f안에서만 유효한 지역 변수입니다. 따라서 함수 바깥에서 읽거나 사용할려고 하면 참조 에러가 뜹니다.
변수에 유효 범위가 있는 이유는 프로그램의 다른 부분에서 선언된 이름이 같은 변수와 충돌하지 않기 위해서입니다. 다른 함수 내부에서 선언된 각각의 지역 변수는 모두 선언된 함수 내부에서만 유효하므로 이름이 같아도 충돌하지 않습니다. 덕분에 함수 안에서 변수 이름을 지을 때는 다른 함수 안에서 사용하는 변수 이름까지 신경써야합니다.
전역변수와 지역변수 이름이 동일하게 된다면 충돌한다. 이떄는 전역 변수를 숨기고 지역 변수를 사용합니다.
var a = "global";
function f() {
var a = "local";
console.log(a); // -> local
return a;
}
f();
console.log(a); // -> global
이 코드에서는 함수 바깥에서 선언한 전역 변수 a, 지역 변수 a 등장합니다. 두 변수는 이름이 같지만 다른 메모리의 위치에 존재하는 별개의 변수라고 생각하면 좋다.
지역 변수 a의 유효 범위 안에서 전역 변수 a는 숨겨집니다. 따라서 첫 번째출력은 local이 됩니다. 함수 바깥은 지역 변수 a의 유효 범위를 벗어나므로 두 번째 출력은 global이 됩니다.
함수 안에서 선언된 지역 변수의 유효 범위는 함수 전체입니다. 함수 중간 부분에서 변수를 선언하더라도 변수는 함수 첫머리에서 선언된 것처럼 함수 안의 다른 문장보다 먼저 생성된다. 즉, 자바스크립트 엔진은 함수 안의 변수 선언부를 함수의 첫머리로 끌어올린다.
function f() {
console.log(a); // undefined
var a = 'local';
console.log(a); // local
return a;
undefined 가 먼저 출력되고 다음에 local 이 출력된다.
이것은 자바스크립트가 a 라는 변수를 인식하여 첫 문장에 a 라는 변수를 첫 머리로 끌어올려서 그렇다.
이것을 hoisting 이라고 한다.
undefiend : 변수는 존재하나, 어떠한 값으로도 할당되지 않아 자료형이 정해지지(undefined) 않은 상태입니다.
변수를 선언하지 않은 상태에서 값을 대입하면 전역 변수로 선언됩니다. 이 현상은 함수 바깥에서 발생하지만 함수 안에서도 발생합니다.
function f() {
a = "local"; // -> var, let, const 없이 선언. 지역변수가 아닌 전역변수로 인식
console.log(a); // -> local
return a;
}
f();
console.log(a);
var, const, let이 없이 선언됬으므로 지역 변수로 선언한 것이 아닌 전역 변수로 선언한 것입니다.
let과 const는 ECMAScript 6부터 추가된 변수 선언자로 모두가 '블록 유효 범위'를 갖는 변수를 선언한다. 블록 유효 범위를 가진 변수는 중괄호({}) 안에서만 유효하다.
var과 가장큰 차이점은 let으로 선언한 변수의 유효범위가 블록 안이라는 것입니다.
let x = "outer x";
{
let x = "inner x"; // 블록 내부에서만 유효한 변수 아래도 동일
let y = "inner y";
console.log(x); // inner x
console.log(y); // inner y
}
console.log(x); // outer x
console.log(y); // Reference Error: y is not defined
아래 코드는 var로 선언했을떄 차이점이다. var로 선언한 변수는 자바스크립트 엔진이 선언문을 평가하기 전에 undefined로 초기화합니다. 이것을 호이스팅이라고 합니다. 자바스크립트 엔진은 let문과, const문으로 선언한 변수도 호이스팅하지만, undefined로 선언문을 평가하기 전에는 초기화하지 않습니다. 이를 Temporal Dead Zone (TDZ) 라고 합니다.
var x = "outer x";
{
var x = "inner x";
var y = "inner y";
console.log(x); // inner x
console.log(y); // inner y
}
console.log(x); // inner x
console.log(y); // inner y
const 문은 블록 유효 범위를 가지면서 한 번만 할당할 수 있는 변수(상수)를 선언합니다. const로 선언한 상수는 let 문으로 선언한 변수처럼 동작합니다. 단, 반드시 초기화 해야하는 차이점이 있다.
const c = 2;
// const문으로 선언한 변수에 다시 대입을 시도할시 타입 에러
c - 5; // uncaught TypeError
// const 문으로 선언한 상수값은 수정할 수 없지만, 상수 값이 객체거나 배열일 경우에는 property 또는 property value를 수정할 수 있습니다.
const origin = {x:1, y:2};
origin.x = 3;
console.log(origin) = Object {x:3, y:2}
var square = function(x) {return x * x;};
function(x) {...} 부분이 함수 리터럴입니다. 함수 리터럴은 이름이 없는 함수이므로 익명 함수 / 무명 함수라고 부른다. 함수 리터럴 사용시 끝에 세미 콜론(;)을 반드시 붙여야 한다.
사용법은 square(5)라고 작성하면 실행됩니다. 이는 함수 리터럴과 함수 선언문이 모두 내부적으로 square 변수에 함수 객체의 참조(위치)를 저장하기 때문입니다. 한 가지 차이점이라면 자바스크립트 엔진이 함수 선언문으로 정의한 함수는 끌어올리지만 함수 리터럴로 정의한 함수는 끌어올리지 않습니다. 함수 리터럴로 정의한 익명 함수는 변수에 할당한 후에야 비로소 square라는 이름을 갖게 되고 이래야 호출이 가능해집니다.
console.log(square(3)); // -> Type Error : square is not defined
var square = function(x) { return x * x; } // 함수 리터럴은 호이스팅 x
익명 함수에도 이름을 붙일 수 있다.
var square = function sq(x) { return x * x }
그러나 코드에서 sq라는 이름은 함수 안에서만 유효하므로 함수 바깥에서는 sq이름으로 사용 x
객체의 프로퍼티 중 함수 객체의 참조를 값으로 담고 있는 프로퍼티를 메서드라고 한다. 메서드를 정의할 떄는 프로퍼티 값으로 함수 리터럴을 대입.
var circle = {
center: { x:1.0, y:2.0 }, // 원의 중점 표현하는 객체
radius: 2.5, // 원의 반지름
area: function() { // 원의 넓이 구하는 메서드
return Math.PI * this.radius * this.radius;
}
};
여기서 this는 이 area라는 메서드를 가지고 있는 객체 즉, circle을 가리킵니다. this.radius = circle.radius와 동일합니다. 메서드는 일반 함수와 마찬가지로 ()로 실행합니다.
또한 메서드도 프로퍼티의 일종이므로 나중에 값을 추가할 수 있습니다. 예를 들어 객체 circle에 원을 평행으로 이동시키는 translate메서드를 추가해보자!
circle.translate = function(a, b) {
this.center.x = this.center.x + a;
this.center.y = this.center.y + b;
};
circle.translate(1, 2);
circle.center; // => Object {x=2, y=4}
즉, 메서드는 일반적으로 메서드가 속한 객체의 내부 데이터(프로퍼티 값) 상태를 바꾸는 용도로 사용한다. 일반적인 객체 지향 언어에서는 데이터와 그 상태를 바꾸는 메서드를 하나로 묶는 용도로 객체를 사용한다.
이러한 객체를 기본 부품으로 삼아 프로그램을 만들어 가는 기법을 가리켜 객체 지향 프로그래밍이라고 부릅니다.
생성자로 객체를 생성해보자. 생성자를 사용하면 이름이 같은 메서드와 프로퍼티를 가진 객체 여러개를 효율적으로 생성할 수 있다.
예시
트럼프 카드를 표현하는 객체를 생성하는 생성자.
function Card(suit, rank) {
this.suit = suit;
this.rank = rank;
}
// 생성자로 객체를 생성할떄는 new 연산자 사용
var card = new Card("하트", "A");
console.log(card); // Card {suit: "하트", rank: "A"}
new연산자로 객체를 생성할 것이라 기대하고 만든 함수를 생성자라고 부른다. 생성자 이름은 관례적으로 그것이 생성자임을 알리기 위하여 첫글자를 대문자로(파스칼 표기법)을 사용한다!
생성자 내부에서 this.프로퍼티 이름에 값을 대입하면 그 이름을 가진 프로퍼티에 값이 할당한 객체가 생성된다. 이떄 this는 생성자가 생성하는 객체를 가리킨다.
객체 리터럴로 고쳐 쓸 수 있다.
var card = {};
card.suit = "하트";
card.rank = "A";
생성자와 new 연산자로 생성한 객체를 그 생성자의 인스턴스라고 부른다. 인스턴스에는 실체라는 뜻이 있다. 객체 지향 언어에서 인스턴스란? 클래스로 생성한 실체를 의미한다. 생성자 또한 클래스처럼 객체를 생성하는 역할을 담당하므로 생성자로 생성한 객체도 인스턴스라고 부르는 것이 관례다.
생성자는 객체를 생성하고 초기화하는 역할을 한다. 생성자를 사용하면 이름은 같지만 프로퍼티 값이 다른 객체(인스턴스) 여러 개를 간단히 생성할 수 있다.
생성자를 활용하여 객체를 생성하고 변수 여러개를 저장할 수 있다. 아래 코드를보자
function Card(suit, rank) {
this.suit = suit;
this.rank = rank;
}
var card1 = new Card("하트", "A");
var card2 = new Card("클로버", "K");
var card3 = new Card("스페이드", "2");
위처럼 생성자를 사용하면 이름은 같지만 프로퍼티 값이 다른 객체 여러 개를 효율적으로 생성이 가능하다!
객체를 생성할 떄 초기화 작업 또한 병핼할 수 있다. particle은 좌표와 속도를 가진 좌표평면 위에 파티클을 표현하는 객체를 생성하는 생성자이다.
function particle(x, y, vx, vy) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
}
var p = new Particle(0, 0, 3, 4); // 값을 대입하여 객체 생성하며 초기화까지 병행
console.log(p); // -> particle {x:0, y:0, vx:3, vy:4, velocity:5}
생성자에서 this.프로퍼티 이름에 함수의 참조를 대입하면 메서드를 정의할 수 있다. 이때 메서드 함수 안에 있는 this는 생성될 인스턴스를 가리킨다.
function Circle(center, radius) {
this.center = center;
this.radius = radius;
this.area = function() { // 메서드 함수안에서 this사용시 그 값은 생성될 인스턴스의 프로퍼티임을 명시
return Math.PI * this.radius * this.radius;
};
}
var p = {x:0, y:0};
var c = new Circle(p, 2.0);
console.log("넓이 = " + c.area()); // 넓이 = 12.566370...
자바스크립트에는 처음부터 사용할 수 있는 내장 객체(빌트인 오브젝트) 가 마련되어있다. 내장 객체는 자바스크립트라는 프로그래밍 언어의 뼈대를 구성합니다.
필요한 내장 생성자등은 나중에 필요할떄 찾아가면서 사용해보자!
배열은 값의 목록으로 값마다 번호가 매겨져 있습니다. 배열을 활용하면 다양한 알고리즘을 표현할 수 있다!!
배열 리터럴은 쉼표로 구분한 값을 대괄호로 묶어서 표현
var evens = [ 2, 4, 6, 8 ]
앞 코드에서 [...] 부분이 배열 리터럴이다. 배열 값 하나를 배열 요소라고 부른다. 0, 1, 2 ... 순서로 번호가 매겨져 있다.
자바스크립트에서의 배열은 객체 타입이므로 배열을 변수에 대입하면 배열의 참조(위치)가 변수에 저장됩니다.
var empty = [];
console.log(empty); // -> [] 빈배열 생성
// 1번 인덱스가 빈채로 배열 생성이 가능합니다.
var a = [2, , 3];
console.log(a); // -> [2, undefined, 3]
// 모든 타입의 값이 올수 있다.
var array = [3.14, "pi", true, {x:2, y:7}, [2, 4, 6, 8] ];
배열은 Array 생성자로 생성 가능!
var evens = new Array(2, 4, 6, 8); // [2, 4, 6, 8]을 생성
var empty = new Array(); // [ ] 빈 배열 생성
var a = new Array (2, 4); // 배열 리터럴 [2, 4]와 동일한 배열 생성
var various = new Array(3.14, "pi", true, {x:1, y:2}, [2, 4, 6, 10]);
varx = new Array(3); // 배열의 길이가 3인 배열을 생성
console.log(x.length); // -> 3 음수값은 x
대괄호([])를 사용하여 읽고 쓸 수 있다.
evens[2] // -> 6(인덱스가 2인 요소 즉, 3번쨰 요소)
C나 Java와 같은 프로그래밍 언어의 배열 요소는 메모리의 연속된 공간에 차례대로 배치되어 있다. 따라서 인덱스를 지정하면 인덱스가 가리키는 요소를 매우 빠르게 읽거나 쓸 수 있다. 그러나 자바스크립트의 배열은 다르다. 자바스크립트의 배열은 Array 객체이다. 객체로 배열의 기능을 가상으로 흉내낸 것. Array 객체는 배열의 인덱스를 문자열로 변환해서 그것을 프로퍼티로 이용!, 즉 배열에 대괄호 연산자를 사용하는 것은 객체에 대괄호 연산자를 사용하는 것과 마찬가지, 배열의 요소 번호로 숫자 값 대신 문자열을 사용할 수 있다.
var a = ["a", "b", "c", "d"];
console.log(a["2"]); // C
a[4] // 없는 배열 요소 읽을시(객체에 없는 프로퍼티를 읽을려 하므로) -> undefined
없는 배열 요소에 값을 대입시 새로운 요소 추가
var a = ["A", "B", "C"];
a[3] = "D";
console.log(a); // -> ["A","B","C","D"]
push 메서드 사용시 배열 끝에 추가 가능.
var a = ["A", "B", "C"];
a[3] = "D";
console.log(a); // ["A", "B", "C", "D"]
delete a[1];
console.log(a); // ["A", undefined, "C", "D"]
배열에 요소를 추가하거나 제거하면 인덱스가 0부터 시작되지 않는 배열이 만들어진다. 이러한 배열을 희소 배열이라고 부른다.
var a = ["A", "B", "C"];
a[4] = "E";
console.log(a); // ["A", "B", "C" , undefined , "E"];
실제로 코드를 실행하여 결과를 보면 a[3] 은 undefined라고 표시되지만 실제로는 없는 값이다.
객체 리터럴로 표시하면 아래와 같다.
{"0":"A", "1":"B", "2":"C", "4":"E" }
희소 배열의 길이는 배열 요소의 개수보다 크다. 희소 배열이 아닌 배열의 길이는 배열 요소의 개수와 같다.
배열 요소가 있는지 확인하기 위해서는 hasOwnProperty 메서드를 활용하자!