여러 속성을 하나의 변수에 저장할 수 있도록 해주는 데이터 타입으로 Key / Value Pair를 저장할 수 있는 구조이다.
문자열이나 숫자 등 한 가지만 표현할 수 있는 기본(primitive) 자료형과는 달리, 객체는 다양한 종류의 데이터를 담을 수 있다. 자바스크립트는 객체 기반 프로그래밍 언어이기 때문에, 객체는 자바스크립트를 구성하는 모든 것으로 여겨지기도 한다.
var user = new Object(); // "object constructor" syntax
var user = {}; // "object literal" syntax
Ex )
let user = { name: "Kate", age: 21 }; // key value key value
let user = { name: "Mimi" };
let admin = user; // copy the reference
{ key : value }
의 목록var person = {
firstName:"John",
lastName:"Doe",
age:50,
eyeColor:"blue"
};
객체 리터럴을 사용하면 한 명령문에서 객체를 정의하고 만들 수 있다.
var person = new Object();
person.firstName = "John";
person.lastName = "Doe";
person.age = 50;
person.eyeColor = "blue";
*단순성, 가독성 및 실행 속도를 위해서라면 첫번째 방법을 사용하는 것을 권장
자바스크립트의 데이터 타입 중 여러 개의 데이터값을 하나로 선언할 수 있는 타입에는 '배열'과 '객체'가 있다. 배열
내 요소들은 인덱스로만 구분
되어지는 반면, 객체의 프로퍼티
는 속성을 나타내는 키
와 그에 대한 값
으로 구성되기 때문에 데이터를 더욱 직관적으로 저장하고 불러올 수 있다.
let person1 = ['Kate', 21, 'Seoul', false];
// 배열
let person2 = {
'name' : 'Kate',
'age' : 21,
'city' : 'Seoul',
'married' : false
}
// 객체 -> 각각의 value가 의미하는 바를 파악하기가 용이함.
key
: 특정한 값을 담을 수 있는 그릇.value
: key에 담긴 특정한 값. 모든 데이터 유형이 가능함.property
: key + value. 객체 내부의 속성.프로퍼티에 값을 할당하지 않을 경우
JavaScript에서 사용하는 변수는 값을 할당하지 않고 선언만 할 경우 자동적으로 undefined를 할당한다. 하지만 객체의 정보를 담고 있어야 할 요소가 그 어떤 정보도 할당받지 않았다면 객체로서는 필요가 없기 때문에 프로퍼티를 추가하면서 값을 할당하지 않으면 syntax error
가 뜬다.
프로퍼티의 삭제
JavaScript의 프로퍼티는 undefined나 null을 할당한다고 삭제되지 않기 때문에 반드시 delete
라는 keyword를 사용하여 프로퍼티를 삭제해주어야 한다.
var foo = new Object();
foo.name = 'foo';
console.log(foo.name); // foo
foo.name = null;
console.log(foo.name); // null
delete foo.name;
console.log(foo.name); // undefined
Dot Notation
객체명.프로퍼티명
: 마침표( .
) 연산자를 사용하며, 접근하려는 객체명은 왼쪽에, 프로퍼티명은 오른쪽에 위치한다.
Bracket Notation
객체명["프로퍼티명"]
: 대괄호( []
)를 사용하여, 접근하려는 객체명은 왼쪽에, 프로퍼티명은 쌍따옴표( ""
)와 함께 대괄호 안에 작성한다.
가장 큰 차이는 property의 변수로 접근 가능 여부이다.
Dot Notation | Bracket Notation |
---|---|
숫자로 시작하는 키에 접근할 수 없다. | |
띄어쓰기가 포함된 키에는 접근할 수 없다. | 모두 가능하다. |
변수가 포함되어 있으면 접근할 수 없다. |
모든 객체 데이터는 속성을 통해 얻는다.
객체명.속성
객체명.속성[인덱스].속성
객체명.속성.속성.속성
과 같이 체인 연결로 최종 속성값, 또는 또 다른 객체를 얻게 된다.
중첩 객체인 경우 속성값으로 객체가 올 수 있으며, 해당 속성으로 접근시 객체가 반환된다. 속성값이 배열일 경우 배열 객체가 반환되며, 배열 길이 및 배열 요소에 속성 체인으로 바로 접근이 가능하다.
객체 속성 추가는 2가지 방법으로 가능하다.
객체["속성"] = 속성값;
객체.속성 = 속성값;
속성값은 객체, 배열, String, Number, Boolean, null 등이 가능하다.
하위 객체에 속성을 추가하는 방법
객체.객체.객체.속성 = 속성값; 객체.객체["속성"] = 속성값;
속성 추가와 같은 방법으로 속성을 수정한다. 기존 속성이 있으면 변경하고, 속성이 없으면 추가하는 구조이다.
객체["속성"] = 새 속성값;
객체 속성 삭제는 조금 독특한 방법을 사용한다. 별도로 delete 연산자가 있으며
delete 객체.속성;
과 같은 방식으로 삭제한다.
delete 연산자는 삭제후 true/false 반환값을 반환한다. 삭제에 성공하면 true, 실패하면 false를 반환한다. 삭제시 조건문 체크를 이용해 삭제 성공 여부에 따른 추가 처리를 할 수 있다.
let friends = { brand: "카카오", original: [{name: "라이언", age: 5}, {name: "어피치", age: 4}], newbee: {name: '네온', age: 3}};
//속성값 얻기 console.log(friends.original[0]); // {name: '라이언', age: 5} console.log(friends.original[1].age); // 4 console.log(friends.original.length); // 2 console.log(friends.newbee.name); // '네온' //속성 추가 friends.newbee['sex'] = 'female'; //객체 배열로 변환 friends["newbee"] = [friends["newbee"], {name:"콘", age:2}]; console.log(friends.newbee); // [{name: "네온", age: 3, sex: "female"}, {name: "콘", age: 2}] //속성 수정 friends.newbee[0]['sex'] = 'male'; //배열 안의 속성에 접근 friends.newbee.sex = 'unknown'; // 적용 안됨 console.log(friends.newbee); // [{name: "네온", age: 3, sex: "male"}, {name: "콘", age: 2}] //속성 삭제 delete friends.newbee[0].sex; friends.newbee.pop(); delete friends.brand; console.log(friends); // {original: [{name: "라이언" ,age: 5}, {name: "어피치" ,age: 4}], newbee: {name: '네온', age: 3}}
객체와 배열을 포함하는 중첩 데이터 구조에 접근하는 방법은 2가지가 있다.
EX1) Bracket Notation 사용
data의 두번째 항목인 items의 속성 name의 값 'bar'을 추출해보자.var data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }; // item_name 변수 선언 // items속성 name의 값 bar추출 const item_name = data['items'][1]['name']; console.log(item_name) //bar
EX) Dot Notation 사용
새로운 변수를 선언하여 Part 1, 60, Part 3A 값을 추출해보자.var someObject = { part1 : { name: 'Part 1', size: '20', qty : '50' }, part2 : { name: 'Part 2', size: '15', qty : '60' }, part3 : [ { name: 'Part 3A', size: '10', qty : '20' }, { name: 'Part 3B', size: '5', qty : '20' }, { name: 'Part 3C', size: '7.5', qty : '20' } ] }; // part1 name 변수를 사용하여 part1의 속성 name의 값 'Part 1'에 접근 var part1name = someObject.part1.name; // part2 quantity 변수를 사용하여 part2의 속성 qty의 값 60에 접근 var part2quantity = someObject.part2.qty; // part3 name1 변수를 사용하여 part3의 첫번째 배열의 속성name의 값 'Part 3A'에 접근 var part3name1 = someObject.part3[0].name; console.log(part1name); //Part 1 console.log(part2quantity); //60 console.log(part3name1); //Part 3A
A. 배열은 자바스크립트의 기본 자료형에 해당하지 않고, 기본 자료형이 아닌 객체형에 속하기 때문에 객체처럼 동작한다.
객체라는 자료구조는 키를 사용해 식별할 수 있는 값(키의 값)을 담은 컬렉션으로 이를 이용해 데이터를 저장할 수 있고 객체만으로도 다양한 작업들이 충분히 가능하다.
<배열이 객체처럼 동작하는 과정들>
배열은 객체와 마찬가지로 참조를 통해 복사한다.
배열은 객체처럼 원하는 프로퍼티를 추가해도 문제가 발생하지 않는다.
*다만 이렇게 코드를 작성하면 자바스크립트 엔진이 배열을 일반 객체처럼 다루게 되어 배열 특유의 이점이 사라지니 배열은 배열답게 사용하자.
배열은 객체형이므로 for..in
을 사용하는 것도 가능하다.
*그러나 for..in
반복문은 배열이 아닌 객체와 함께 사용할 때 최적화되어 있어서 배열에 사용하면 객체에 사용하는 것 대비 10~100배 정도 느리다. 따라서 배열엔 되도록 for..of
반복문을 사용한다.
A. 개발을 하다 보면 첫 번째 요소, 두 번째 요소, 세 번째 요소 등과 같이 순서가 있는 컬렉션이 필요할 때가 있다.
이렇게 순서가 있는 컬렉션을 다뤄야 할 땐 객체를 사용하면 순서와 관련된 메소드가 없어 불편하다. 객체는 태생이 순서를 고려하지 않고 만들어진 자료구조이기 때문에 객체를 이용하면 새로운 프로퍼티를 기존 프로퍼티 사이에 끼워 넣는 것도 불가능하다.
이처럼 순서가 있는 컬렉션을 저장해야하는 상황이 생길 때 쓰는 자료구조가 바로 배열이다.
A. 함수는 객체가 값이기 때문에 함수를 일급 객체로 여긴다.
이처럼 함수가 일급 객체라는 건 함수를 객체와 동일하게 사용할 수 있다는 것을 의미한다. 객체는 값이므로 함수 역시 값과 동일하게 취급한다. 자바스크립트의 함수는 값처럼 변수에 할당할 수 도 있고 프로퍼티 값이 될 수도, 배열의 요소가 될 수도 있다. 이렇게 값의 성질을 갖는 객체를 일급객체라고 합니다.
<배열이 객체처럼 동작하는 과정들>
//변수 variable에 함수 리터럴을 할당한 식
const cal = function add(x, y){
return x + y;
}
위 코드는 함수 리터럴을 변수에 할당하고 있다. 따라서 함수 리터럴도 평가되어 값을 생성하고 있다.
// 변수에 함수 할당
const name = function() { return 'Kate'; };
console.log(name()); // Kate
// 프로퍼티에 함수 할당
const obj = {};
obj.langauge = function() { return 'JavaScript'; };
console.log(obj.langauge()); // JavaScript
위 코드의 langauge처럼 객체의 프로퍼티에도 함수를 할당할 수 있고 배열의 원소로도 할당이 가능하다.
// 함수 표현식으로 toss() 함수를 생성
const toss = function(func) {
func(); // 인자로 함수를 넘겨받고 넘겨받은 func() 함수를 호출한다.
}
//toss() 함수 호출 시
toss(function(){ // toss 함수의 인수로 함수 자체를 전달한다.
console.log('함수의 인자로 전달되었습니다.'); // '함수의 인자로 전달되었습니다.'
});
toss() 함수를 호출 시 함수 자체를 func 인자로 넘겨서 toss() 함수 내부에서 func 매개변수로 인자에 넘겨진 함수를 호출합니다.
// 함수를 다른 함수의 리턴값으로 활용한 코드
// 함수를 리턴하는 foo() 함수 정의
const foo = function() {
return function() { // 함수를 리턴
console.log('이 함수는 함수를 반환한다.');
};
};
// foo() 함수가 호출되면, 리턴값으로 전달되는 익명함수가 bar 변수에 저장됨.
const bar = foo();
// 익명함수를 호출하기 위해서 ()인 함수호출 연산자를 이용해 bar()로 익명함수를 호출, 실행.
bar(); // ('이 함수는 함수를 반환한다.')
function minus(x,y) {
return x - y;
}
// 함수 역시 객체처럼 프로퍼티를 가질 수 있음.
// 함수 객체에 anwser 프로퍼티를 추가하고 값으로 함수를 호출하여 넘겨줌.
minus.result = minus(4,1);
console.log(minus.result); // 1
함수 자체가 일반 객체처럼 프로퍼티를 생성하고 할당이 가능하다. minus()함수는 result 프로퍼티를 생성하고 minus()함수 호출 결과 값을 생성한 함수의 result 프로퍼티에 저장할 수 있다. 일반 객체의 접근 방식처럼 minus.result를 이용해 접근도 가능하다.
ECMA Script에서 객체는 아래와 같이 크게 3가지로 구분하고 있다.
JavaScript 엔진이 구동되는 시점에서 바로 제공되며 JavaScript코드 어디에서든 사용이 가능하다. 아래의 내장 객체들 외에도 많은 내장 객체들이 있다.
- Global
- Object / Array
- String / Number / Boolean
- Date
- Math
브라우저 내장 객체 또한 JavaScript가 구동되는 시점에서 바로 사용이 가능한 객체들이며 내장 객체이다. 하지만 브라우저마다 브라우저 내장 객체를 사용함에 있어 구성을 달리하는 경우가 있기 때문에 JavaScript 내장 객체와 분류해 두었다. 하지만 브라우저 내장 객체는 브라우저, 즉 JavaScript 엔진을 구동하는 것들에서 build되는 객체들이다. 예시로는 BOM과 DOM이 있다. 이 객체들은 자바스크립트 내장객체가 구성된 후에 구성된다.
- 브라우저 객체 모델 (BOM)
- 문서 객체 모델 (DOM)
말 그대로 사용자가 생성한 객체들로 생성자 함수 또는 객체 리터럴을 통해 사용자가 객체를 정의하고 확장시킨 객체들이기 때문에 내장 객체들이 구성된 이후에 구성된다.