객체란?
원시 타입 vs 객체 타입
- 원시 타입
- 구성
- 숫자 타입(number)
- 문자열 타입(string)
- 불리언 타입(boolean) → 참, 거짓
- undefined 타입(undefined) → var 키워드 선언 변수에 암묵적으로 할당되는 값
- null 타입(null) → 값이 없다는 것을 명시할 때 사용
- 심벌 타입(symbol) → ES6에서 추가
- 변경 불가능한 값
- 구성
- 객체 타입
- 구성
- 객체(object) → 프로퍼티, 메서드로 구성
- 배열(array)
- 함수(function)
- 변경 가능한 값
- 구성
객체 리터럴에 의한 객체 생성
객체 리터럴
var person = {
name: 'Lee', //프로퍼티
sayHello: function(){ //메서드
console.log(`Hello! My name is ${this.name});
}
};
console.log(person); // {name: "Lee", sayHello: f}
- 객체 리터럴에 의한 객체 생성은 중괄호 내에 0개 이상의 프로퍼티를 정의하는 것으로 진행된다.
- 해당 person 객체의 구성
- name: ‘Lee’ → 프로퍼티
- sayHello: fuction()→ 메서드
- 프로퍼티를 0개 정의한다면?
var empty = {};
console.log(empty); // {}
-> 빈 객체가 생성됨
- 객체에 메소드만 정의한다면?
var person = {
hello: function () {
console.log('hello!');
}
};
console.log(person); // { hello: [Function: hello] }
프로퍼티
- 객체의 상태를 나타내는 값
- 키와 값으로 구성되어 있다.
- 프로퍼티 키가 식별자 네이밍 규칙을 따르지 않으면 반드시 따옴표를 사용
var foo = {
name: 'Kim' //키와 값으로 구성
}
식별자 네이밍 규칙
- 식별자는 특수문자를 제외한 문자, 숫자, _ , $ 만을 포함
- 식별자는 특수문자를 제외한 문자, 숫자, _ , $ 로 시작해야 한다. 숫자로 시작하는 것은 허용하지 않는다.
- 예약어는 식별자로 사용할 수 없다.
//식별자 네이밍 규칙을 위반하는 프로퍼티 키
'last-name': 'Lee'
'last name': 'Lee'
'2lastname': 'Lee'
if: 'Lee' //예약어는 규칙 위반이지만 허용은 한다.
프로퍼티 선언 시 주의할 점
var foo = {
name: 'Kim' //정상적 선언
0: 1 //숫자 리터럴 사용시 문자열로 변환
'': '' //빈 문자열도 키로 사용 가능
name: 'Lee' //중복선언 시 값 덮어씀
}
console.log(foo); // { '0': 1, name: 'Lee', '': '' }
메서드
- 프로퍼티 값이 함수인 것
var circle = {
radius: 5,
getDiameter: function(){
return 2 * this.radius;
}
};
console.log(circle.getDiameter()); // 10
프로퍼티 접근
마침표 표기법
var person = {
name: 'Lee'
};
console.log(person.name); // Lee
console.log(person.age); // undefined
- 객체에 존재하지 않는 프로퍼티 접근 시 undefined 반환
대괄호 표기법
var person = {
name: 'Lee'
};
console.log(person['name']); // Lee
console.log(person[name]); // Error
- 반드시 따옴표로 감싼 문자열이어야 함
- 따옴표로 감싸지 않으면 에러 발생
이처럼 프로퍼티 키가 식별자 네이밍 규칙을 준수하는 이름이면 마침표 표기법, 대괄호 표기법 둘 다 사용 가능하다.
그렇다면 이를 위반하는 이름이면 어떨까?
var person = {
'last-name': 'Lee',
1: 10
}
- 마침표 표기법
마침표 표기법을 이용하면 원하는 값에 접근할 수 없다.
*NaN이 발생하는 이유?
💡 ‘-’ 를 연산자로 인식하기 때문이다. 이 때문에 person.last와 name을 나누어 생각하는데 person.last는 undefined를 반환하고, name는 전역변수로 암묵적으로 존재하기 때문에 빈 문자열을 반환한다. 결국 **undefine - ‘’**형태가 되므로 이는 NaN라는 결과가 나오는 것이다.
- 대괄호 표기법
person[last-name]; //Error
person['last-name']; //Lee
person[1]; //10
person['1']; //10
대괄호 내에서는 따옴표를 반드시 써주어야 한다. 하지만 숫자 리터럴의 경우, 문자열로 자동 변환되기 때문에 person[1]과 person[’1’]은 같은 표현이 된다. 결국 키 값이 숫자 리터럴인 경우 따옴표를 쓰지 않아도 된다.
💡 결론적으로, 프로퍼티 키가 식별자 네이밍 규칙을 위반하는 이름이면 마침표 표기법은 사용할 수 없고, 대괄호 표기법은 조건부 허용된다.
프로퍼티 CRUD
프로퍼티 갱신
ver person = {
name: 'Lee'
};
person.name = 'Kim';
person['name'] = 'Kim';
console.log(person); //{name: 'Kim'}
이미 존재하는 프로퍼티에 값을 할당한다.
프로퍼티 생성
var person = {
name: 'Lee'
};
person.age = 20;
console.log(person); //{name: 'Lee', age: 20}
//프로퍼티 키 동적 생성
var key = 'hello';
person[key] = 'world';
console.log(person); //{name: 'Lee', age: 20, hello: 'world'}
존재하지 않는 프로퍼티에 값을 할당한다.
프로퍼티 삭제
var person = {
name: 'Lee'
};
delete person.name; //삭제
delete person.address; //에러 발생하지 않음
console.log(person); // {}
delete 연산자를 이용하여 삭제한다. 이때, 존재하지 않는 프로퍼티를 삭제하면 무시된다.
이 외의 기능
프로퍼티 축약
//프로퍼티 값인 변수 이름과 프로퍼티 키가 동일한 이름일 경우
var x = 1, y = 2;
var obj = {
x: x,
y: y
};
var obj = { x, y };
프로퍼티 값으로 변수를 사용하는 경우 변수 이름과 프로퍼티 키가 동일한 이름일 때 프로퍼티 키를 생략할 수 있다.
메서드 축약
var obj = {
name: 'Lee',
sayHi: function(){
console.log('Hi! ' + this.name);
}
sayHi() {
console.log('Hi! ' + this.name);
}
//두 메서드는 동일한 표현
}
function 키워드를 생략한 축약 표현 사용 가능하다.
계산된 프로퍼티
//프로퍼티 키가 대괄호로 둘러쌓인 프로퍼티
const fs = require('fs');
console.log('과일을 입력하세요: ');
var fruit = fs.readFileSync(0, 'utf8').toString().split(' ');
var bag = {
[fruit]: 5,
};
console.log(bag.apple);
//fruit가 'apple'일 때 5출력
//아닐 때 undefined 출력
var i = 0;
var prefix = 'prop';
var obj = {};
obj[prefix + '-' + ++i] = i;
obj[`${prefix}-${++i}`]: i;
console.log(obj); //{prop-1: 1}
문자열 또는 문자열로 타입 변환할 수 있는 값으로 평가되는 표현식을 사용해 프로퍼티 키를 동적으로 생성할 수 있다.
반드시 대괄호 표기법을 사용해야 한다.
존재 여부 확인
let user = { name: "John", age: 30 };
console.log("age" in user); //true
console.log("asdf" in user); //false
in을 이용해 프로퍼티가 존재하는지 확인할 수 있다.
‘따옴표로 감싸진 프로퍼티 키 in 객체 이름’ 형태로 대입해야 한다.
프로퍼티가 존재하면 true, 존재하지 않으면 false 반환
키 순회
let user = { name: "John", age: 30 };
for(let key in user){
console.log(key); //name, age -> 프로퍼티 키
console.log(user[key]); //John, 30 -> 프로퍼티 값
}
for…in 을 이용하여 프로퍼티 키를 모두 순회한다.
이때 프로퍼티 값에 접근하려면 user[key] 형태를 이용한다.
간단한 응용
var person = {
firstName: ['Lee', 'Kim'], //프로퍼티
"last name": ['name', 'nname'], //프로퍼티
age: 20, //프로퍼티
getAge: function () { //메서드
return this.age;
},
increase: function () { //메서드
this.age++;
},
sayHello: function (i) { //메서드
person.firstName.forEach((curElement, curIndex) => {
if (i === curIndex) {
//person['firstName'][i] 대신 this.firstName[i] 도 사용 가능
//하지만 person['last name'][i] 대신 this.'last name[i]' || this.'last name'[i] 사용 불가
console.log(`Hello! My name is ${person['firstName'][i]} ${person['last name'][i]}`)
}
});
}
};
firstName
- 프로퍼티
- 값을 배열로 선언
firstName: ['Lee', 'Kim']
//마침표 표기법
console.log(person.firstName); //[ 'Lee', 'Kim' ]
console.log(person.firstName[0]); //Lee
//프로퍼티 값이 배열일 때 접근 방법
//대괄호 표기법
console.log(person['firstName'][0]); //Lee
console.log(person['firstName[0]']); //undefined
//하위 namespace 생성
firstName: {
first: 'Lee',
last: 'Kim'
}
//호출 시
console.log(person.name.first);
console.log(person['name']['first'])
console.log(person.name.last)
console.log(person['name']['last'])
last name
- 프로퍼티
- 값을 배열로 선언
- 식별자 네이밍 규칙 위반 ⇒ 따옴표 생략 불가
"last name": ['name', 'nname']
//마침표 표기법
console.log(person.last name); //오류
console.log(person.'last name'); //오류
//대괄호 표기법
console.log(person['last name']); //[ 'name', 'nname' ]
console.log(person['last name'][0]); //name
- 대괄호 표기법만 사용 가능
age
- 프로퍼티
- 값을 숫자로 선언
age: 20
//마침표 표기법
console.log(person.age); //20
//대괄호 표기법
console.log(person['age']); //20
getAge()
- 메소드
- age 값을 반환
getAge: function () {
return this.age;
}
console.log(person.getAge()); //20
increase()
- 메소드
- age 값을 +1 한 후 반환
increase: function () {
this.age++;
}
person.increase();
console.log(person.age); //21
sayHello()
- 메소드
- 인덱스 번호를 인수로 하면 그 번호의 firstName과 last name 출력하는 함수
sayHello: function (i) {
person.firstName.forEach((curElement, curIndex) => {
if (i === curIndex) {
//person['firstName'][i] 대신 this.firstName[i] 도 사용 가능
//하지만 person['last name'][i] 대신 this.'last name[i]' || this.'last name'[i] 사용 불가
console.log(`Hello! My name is ${person['firstName'][i]} ${person['last name'][i]}`)
}
});
}
for (let i = 0; i < person['firstName'].length; i++) {
person.sayHello(i);
}
//Hello! My name is Lee name
//Hello! My name is Kim nname
'Frontend > JavaScript' 카테고리의 다른 글
[JavaScript] 제너레이터와 async/await (0) | 2023.02.16 |
---|---|
[JavaScript] DOM 이벤트 (0) | 2023.02.16 |
[JavaScript] Set (2) | 2023.02.16 |
[JavaScript] 이터러블 (1) | 2023.02.16 |
[JavaScript] 함수와 일급 객체 (0) | 2022.11.08 |