자바스크립트는 객체 기반의 프로그래밍 언어이다.
JS를 구성하는 거의 모든 것이 객체인데, 실제로 원시값을 제외한 나머지 값들은 모두 객체이다.
객체는 0개 이상의 프로퍼티로 구성된 집합이며 key와 value로 구성되어 있다.
var person = {
name: "정민규", //프로퍼티
age : "26", //프로퍼티
};
특히 JS의 함수는 일급 객체이므로 값으로 취급할 수 있다. 함수를 프로퍼티 값으로 사용할 수 있다는 말이며 해당 경우 일반 함수와 구분하기 위해서 메서드 라고 칭한다.
var counter = {
num: 0,
increase: function() {
this.num++;
}
};
위 코드에서 increase가 메서드가 된다.
JS에서 함수와 객체는 밀접한 관계를 가진다. 함수로 객체를 만들기도 하며 함수 자체가 객체이기도 하기 때문이다.
객체 리터럴에 의한 객체 생성
C++ 이나 자바같은 클래스 기반 객체지향 언어는 클래스를 사전에 정의하고 new 연산자를 활용해 생성자를 호출하는 방식으로 객체를 생성한다. JS는 프로토타입 객체지향 언어로 클래스 기반 객체지향 언어와는 다르게 여러가지 객체 생성 방법을 지원한다.
1. 객체 리터럴
2. Object 생성자 함수
3. 생성자 함수
4. Object.create 메서드
5. 클래스(ES6)
위 방식중에서 가장 일반적이고 간단한 방법은 객체 리터럴이다.
아래와 같이 객체를 만들어내고 사용할 수 있다.
var person = {
name: 'Jeon',
sayHello: function() {
console.log(`Hello! My name is ${this.name}.`);
}
};
console.log(typeof person); // object
console.log(person); // { name : "Jeon", sayHello: f}
만약 중괄호 내에 프로퍼티를 정의하지 않으면 빈 객체가 생성된다.
var empty = {};
console.log(typeof empty); // object
프로퍼티
객체는 프로퍼티의 집합이며 프로퍼티는 Key와 Value로 구성된다.
프로퍼티 키는 프로퍼티 값에 접근할 수 있는 이름이지만 반드시 식별자 네이밍 규칙을 따라야 하는 것은 아니다. 다만 식별자 네이밍 규칙을 준수하는 프로퍼티와 그렇지 않은 프로퍼티 키는 약간의 차이가 있다.
심벌 값도 프로퍼티 키로 사용할 수 있지만 일반적으로는 문자열을 사용한다. 따라서 프로퍼티 키는 따옴표로 묶어줘야 한다.
하지만 식별자 네이밍 규칙을 준수하는 이름인 경우에는 따옴표를 생략하는것이 가능하다.
var person = {
firstName : 'minGyu',
'last-name' : 'Jeong',
}
위 예시를 보면 이해가 될 것이다.
만약 last-name에 따옴표를 붙이지 않으면 -를 마이너스 연산자로 취급할 것이다.
문자열을 문자열로 평가되는 표현식을 활용해서 Key에 넣는것도 가능하다. 이 경우에는 표현식을 .이 아닌 [...] 를 활용해야 한다.
var obj = {};
var key = 'hello';
// ES5
obj[key] = 'world';
// ES6
// var obj = { [key] : 'world' };
console.log(obj);
프로퍼티 키에 문자열이나 심벌 값 외의 값을 사용하면 암묵적 타입 변환을 통해서 문자열이 된다.
var foo = {
0 : 1,
1 : 2,
}
console.log(foo) // {0:1 , 1:2,}
신기하게 var , function과 같은 예약어를 프로퍼티 키로 사용해도 에러가 발생하지는 않지만 예상치 못한 에러가 발생할 여지가 존재하기에 권장되는 방법은 아니다.
이미 존재하는 프로퍼티 키를 중복 선언하면 나중에 선언한 프로퍼티가 먼저 선언한 프로퍼티를 덮어쓰게 된다. 해당경우 에러가 아니라 덮어쓰게 된다는 포인트에 집중하자.
메서드
자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값으로 사용할 수 있다고 했다. 따라서 조금 전에 설명했듯이 함수 또한 프로퍼티로 사용할 수 있고 이를 메서드라고 부르게 된다.
함수는 이번 시간 말고 곧 이어서 더 자세하게 한번 알아보자.
프로퍼티 접근
프로퍼티에 접근하는 방법에는 크게 두가지가 존재한다.
1. (.) 을 활용
2. ([])을 활용
프로퍼티 키가 식별자 네이밍 규칙을 준수한다면 1번과 2번 모두 사용이 가능하지만 그렇지 않은 경우에는 대괄호 표기법만 사용할 수 있다.
const obj = {
name: 'Jeong';
}
console.log(obj.name) // 'Jeong'
console.log(obj['name']) // 'Jeong'
console.log(obj[name]) // ReferenceError: 식별자로 해석, 선언되지 않은 식별자일 경우
console.log(obj.age) // undefined: 객체에 존재하지 않는 프로퍼티에 접근한 경우
대괄호 표기법의 경우 위에서 나왔듯이 따옴표로 감싸주지 않으면 식별자로 해석하기 때문에 해당 부분을 유의하자
조금 독특한 예시를 하나 보자. 아래와 같은 코드가 있다.
const obj = {
'firse-name': 'Jeong';
}
console.log(obj.first-name) // Node.js환경: ReferenceError
// 브라우저 환경: NaN
위 코드는 신기하게 Node.js환경과 브라우저환경이 다르게 작동한다.
분명 first-name의 -는 마이너스 연산자로 작동될 것이기 때문에
obj.first - name 이란 계산식이 동작하게 된다. 물론 first라는 키가 없기 때문에 undefined로 평가 될텐데, 이후 name이라는 식별자가 없기 때문에 ReferenceError(참조에러) 를 내보내게 된다.
하지만 브라우저에서는 window객체에 name 전역 변수가 암묵적으로 존재하기 때문에 NaN이란 결과값을 내보내게 된다.
프로퍼티 값 갱신
이미 존재하는 프로퍼티에 값을 할당하면 프로퍼티 값이 갱신된다. 마치 변수의 값을 갱신하는 것과 똑같다.
var person {
name : 'mingyu'
}
person.name = 'mingyoo'
프로퍼티 동적 생성
존재하지 않는 프로퍼티에 값을 할당하면 알아서 프로퍼티가 동적으로 생성된다.
var person {
name : 'mingyu'
}
person.lastName = 'Jeong'
프로퍼티 삭제
delete 연산자를 활용하면 객체의 프로퍼티를 삭제한다. 만약 존재하지 않는 프로퍼티를 삭제하려고 하면 에러를 내보내는 것이 아닌 무시되게 된다.
var person {
name : 'mingyu'
}
person.name = 'mingyoo'
delete person.name
ES6에서 추가된 객체 리터럴의 확장 기능
ES6에서 더욱 간편하고 표현력 있는 객체 리터럴의 확장기능이 추가되었다!
만약 프로퍼티 값이 변수에 할당된 값인 경우, 프로퍼티의 키와 그 변수이름이 같다면 이를 축약하여 사용할 수 있다.
const x = 1
const obj = {
x: x
}
console.log(obj) //{ x: 1 }
//위코드와 동일
const x = 1
const obj = {x}
console.log(obj) //{ x: 1 }
계산된 프로퍼티 이름
문자열 혹은 문자열로 타입 변환할 수 있는 값으로 평가되는 표현식을 사용해 프로퍼티 키를 할당하려면 리터럴 표기법 외에서 대괄호로 묶었어야 했지만, ES6 이후에서는 리터럴 내부에서 생성할 수 있게 되었다.
const prefix = 'prop';
let i = 0;
const obj = {
[`${prefix}-${++i}`]: i,
[`${prefix}-${++i}`]: i,
[`${prefix}-${++i}`]: i
}
console.log(obj) //{prop-1: 1, prop-2: 2, prop-3: 3}
메서드 축약 표현
ES5에서는 메서드를 정의하기 위해서 프로퍼티 값으로 함수를 할당하였지만 이젠 그러지 않아도 된다.
const obj = {
//ES5 방식
sayHi: function(){
console.log('Hi');
}
//ES6 방식
sayHi(){
console.log('Hi');
}
}
'FrontEnd > Deep Dive' 카테고리의 다른 글
[JS] DeepDive(12) 함수 (0) | 2023.07.31 |
---|---|
[JS] DeepDive(11) 원시 값과 객체의 비교 (0) | 2023.07.28 |
[JS] DeepDive(9) 타입 변환과 단축 평가 (0) | 2023.07.26 |
[JS] DeepDive(8) 제어문 (0) | 2023.07.22 |
[JS] DeepDive(7) 연산자 (0) | 2023.07.21 |