티스토리 뷰
▶객체와 타입
자바스크립트의 타입은 다른 언어들과 달리 매우 느슨합니다.
데이터 타입과 상관없이 var, let, const와 같은 키워드로 변수를 선언합니다.
엄격한 타입 언어가 아니라서 각 타입의 특징과 타입 변환에 대해 제대로 이해하지 못하면, 원치 않는 동작으로 애플리케이션에 에러가 발생하기도 합니다.
자바스크립트의 값은 원시 타입(Primitive Type)과 객체(참조형)로 나뉩니다.
원시 타입은 다음처럼 7가지가 있습니다.
- number
- string
- boolean
- null
- undefined
- Symbol
- BigInt(ES2020에서 추가)
원시 타입은 하나의 값만 가지며, 불변 데이터이기 때문에 연산을 해도 기존 값이 변경되지 않습니다.
const result = 'hello' + 'javascript';
위의 코드는 'hello' 문자열과 'javascript' 문자열을 병합하는 연산을 수행합니다.
연산 결과는 'hellojavascript' 문자열이 result라는 변수의 값으로 할당되지만, 'hello'와 'javascript'라는 두 문자열 자체의 값은 변하지 않습니다.
원시타입을 제외한 나머지는 모두 객체입니다.
자바스크립트에서는 함수, 배열, 정규식 등도 객체에서 파생된 특수한 타입일 뿐입니다.
▷number
자바스크립트의 숫자 타입은 정수, 실수 구분 없이 숫자 타입 한 가지만 존재합니다.
숫자 타입은 모든 데이터를 64비트의 부동 소수점 형태로 저장하기 때문에 진정한 정수 데이터는 존재하지 않습니다.
자바스크립트의 숫자는 10진수 리터럴을 기본으로 사용합니다.
이 외에도 2진수, 8진수 등 다양한 리터럴을 사용할 수 있습니다.
const num = 8;
// 2진수 리터럴(0b로 시작)
const binaryNum = 0b1111;
// 8진수 리터럴(0o로 시작)\
const octNum = 0o17;
① NaN
자바스크립트에서는 NaN이란 특별한 속성이 존재합니다.
NaN은 Not A Number(숫자가 아님)를 표현하는 값이며, 읽기 전용 속성입니다.
숫자로 변환할 수 없는 값을 숫자로 변환하려고 하거나 산술 연산의 결과가 숫자가 아니면 NaN 값이 반환됩니다.
const a = 3 - 'a';
console.log(a) // NaN
NaN은 자기 자신과도 동등하지 않은 결과를 반환하기 때문에 ES2015에서 추가된 Number.isNaN() 메서드를 사용해 판별하는 것을 권장합니다.
const a = 3 - 'a';
console.log(a == a); // false
console.log(Number.isNaN(a)); // true
② 정수 범위
숫자의 최댓값은 Number.MAX_VALUE(약 1.798e+308)로 정의합니다.
최솟값은 5e-324로 0에 가까운 가장 작은 양의 정수이며 Number.MIN_VALUE로 정의합니다.
하지만 안전하게 표현할 수 있는 정수 값의 범위는 Number.MAX_VALUE보다 훨씬 작은 범위입니다.
따라서 숫자의 범위는 Number.MAX_SAFE_INTEGER(2^53-1)와 Number.MIN_SAFE_INTEGER(-(2^53-1)) 사이로 정의하는 것이 좋습니다.
이 범위를 넘어선 숫자의 연산은 부정확한 결과를 반환할 수 있어 주의해야 합니다.
이 무제를 해결하려면 ES2020에서 새로 등장한 BigInt 타입을 사용하거나 큰 수에 대한 연산 처리를 하는 라이브러리를 사용해야 합니다.
const safeMinNum = Number.MIN_SAFE_INTEGER;
console.log(safeMinNum); // -9007199254740991
// 범위를 벗어나는 연산을 하면 올바른 결과를 얻을 수 없습니다.
console.log(safeMinNum - 4) // -9007199254740996
③ 소수점 연산
자바스크립트의 널리 알려진 소수점 연산의 문제점을 알아볼까요?
자바스크립트는 부동 소수점의 배정밀도를 이요해 근삿값으로 소수점 연산을 수행합니다.
배정밀도는 높은 정밀도를 가지지만 정확한 값을 표현할 수 없어 아래와 같은 문제가 발생합니다.
0.1 + 0.2 == 0.3 // 결과는 false
놀랍게도 결과는 false입니다.
정확한 값이 아닌 근삿값 연산이기 때문입니다.
실제로 0.1과 0.2의 덧셈 연산 결과도 0.3이 아닌 0.300000000000004의 결과를 보입니다.
이러한 자바스크립트의 숫자 연산 문제는 Number.EPSILON을 사용해 해결할 수 있습니다.
*Number.EPSILON : ES2015부터 내장된 속성으로 컴퓨터가 이해하는 가장 작은 숫자 단위
const x = 0.2, y = 0.3, z = 0.1;
let equal = (Math.abs(x - y + z) < Number.EPSILON);
하지만 너무 걱정하지 않으셔도 됩니다.
정밀한 소수점 연산 또는 굉장히 큰 단위의 연산이 필요하지 않다면, 자바스크립트의 숫자 연산은 믿고 사용해도 됩니다.
▷string
string은 텍스트를 표현하는 타입입니다.
자바스크립트의 문자열은 리터럴 형태로 주로 사용하며, 홑따옴표, 쌍따옴표, 백틱(``)이용해 표현합니다.
const str1 = 'hello';
const str2 = "hello";
const str3 = `hello`;
자바스크립트의 문자열은 16비트의 유니코드 문자 집합을 연속적으로 나열한 것입니다.
문자열의 길이는 16비트 코드의 개수로, 대부분은 문제가 없지만 특수한 문자열들은 실제 표현되는 문자열의 길이와 다를 수 있습니다.
const str = 'b"';
console.log(str.lenght); // 2
위 코드처럼 특수한 기호나 문자열을 사용한다면 문자열의 길이가 예상과 다를 수 있으니 주의해야 합니다.
① 이스케이프
문자열을 사용하다 보면 홑따옴표 또는 쌍따옴표를 텍스트 데이터로 표현해야 할 때가 있습니다.
이럴때는 역슬래시(\) 문자로 이스케이프 처리해 사용합니다.
const message = 'Don\'t try this at home';
이 외에도 줄바꿈 문자(\n)처럼 이스케이프 표현을 사용해 나타내는 특수 문자들이 있습니다.
- \n : 줄바꿈문자
- \t : 수평 탭
- \f : 폼 피드
- \r : 캐리지 리턴
- \v :수직 탭
- \u : 네 개의 16진수 숫자로 표현한 유니코드 문자
② 템플릿 리터럴
코드를 작성하다 보면 정해진 포맷의 문자열에 조건에 따른 변수나 상수를 조합해야 하는 일이 많습니다.
const name = 'javascript';
const sentence = 'I love the' + name;
ES2015 이전에는 문자열을 병합해야만 변수나 상수를 문자열 안에 쓸 수 있었습니다.
하지만 이 방법은 문자열 안에 써야 하는 변수나 상수가 많다면 쓰기도 번거롭고 가독성이 덜어진다는 단점이 있습니다.
ES2015의 템플릿 리터럴 문법이 등장하면서, 문자열 내의 변수나 상수를 간결하게 표현할 수 있게 되었습니다.
템플릿 리터럴은 홑따옴표, 쌍따옴표를 사용하지 않고 백틱을 사용합니다.
템플릿 리터럴 안에서는 달러 기호와 중괄호(${})로 표현식을 감싸 문자열 안에 그 값을 삽입할 수 있습니다.
위에 코드를 템플릿 리터럴을 사용해서 변경해봅시다.
const name = 'javascript';
const sentence = `I love the &{name}`;
덧셈 연산자를 사용하는 기존 코드보다 훨씬 간결하게 작성할 수 있습니다.
또한 템플릿 리터럴은 여러 줄의 문자열을 간결하게 표현할 수도 있습니다.
// 아래의 템플릿 리터럴의 평가 결과는 'line 1\nline2'문자열과 같습니다.
console.log(`Line 1
Line2`);
▷boolean
불리언 타입은 true, false.두 가지 값만을 가지며 참과 거짓을 표현할 때 사용합니다.
명시적으로 불리언 값을 할당해 사용하기도 하지만 관계 연산의 결과값 형태로도 자주 사용합니다.
참과 거짓을 판단하는 불리언 타입의 특성상 조건문이나 반복문의 조건 표현식 내에서 많이 사용합니다.
if (a > 1) {
b = 1;
} else {
b = 2;
}
▷null과 undefined
null은 값이 없음을 나타내는 특별한 타입입니다.
대대수 프로그래밍 언어에서 사용하는 것처럼 값이 없음을 나타내고 싶을 때 null 타입을 사용합니다.
하지만 자바스크립트에서는 값이 없음을 나타내는 또 다른 타입 undefined가 있습니다.
값이 할당되지 않는 변수나 반환 값이 없는 함수의 결과값은 자동으로 undefined 값이 할당됩니다.
let v;
function f() {}
console.log(v); // undefined
console.log(f()) // undefined
자바스크립트에 익숙하지 않은 개발자들은 null과 undefined 두 가지로 값이 없음을 표현하는 것에 혼란스러워합니다.
한 가지 팁이라면, 의도적으로 값이 없음을 나타내고 싶을 때 null을 사용하고,
값이 할당되지 않음을 나타내고 싶을 때 undefined를 할당합니다.
하지만 대부분 값이 할당되지 않음을 나타내고 싶을 때는 없기 때문에 주로 null을 사용해 값이 없음을 나타낼 때가 많습니다.
명확한 규칙을 만들고 사용한다면 큰 혼란은 없을 것입니다.
▷Symbol
심볼(Symbol)은 ES2015에서 도입된 원시 타입니다.
데이터의 유일함을 나타낼 때 사용하며, 생성된 심볼은 다른 어떤 심볼과도 일치하지 않습니다.
심볼은 다른 원시 타입과는 달리 Symbol() 함수를 호출해 생성합니다.
여기서 눈여겨볼 점은 new 키워드를 붙이지 않고 심볼을 생성하는 것입니다.
심볼은 객체가 아닌 원시 타입이기 때문에 new 키워드를 사용해 생성할 수 없습니다.
const sym1 = Symbol('key');
const sym2 = Symbol('key');
console.log(sym1 == sym2); // false
① 전역 심볼
전역 심볼을 생성해 매번 새로운 심볼을 생성하지 않고 기존 심볼을 검색해 사용하기도 합니다.
Symbol.for() 메서드를 사용하면 전역 심볼을 생성하며, 전역 심볼을 사용할 때는 다른 라이브러리들과 충돌을 피하도록 prefix를 사용해 구분하는 것이 좋습니다.
const sym1 = Symbol.for('myApp.key');
console.log(sym1 == Symbol.for('myApp.key')) // true
② 심볼의 활용
심볼은 객체나 클래스에서 유일한 프로퍼티를 만들 때 사용합니다.
심볼을 사용해 프로퍼티를 만들면 유일함이 보장되어 프로퍼티 추가 시 충돌이 날 염려가 없습니다.
또한 외부에서 직접 해당 프로퍼티에 접근할 수 없어 의도치 않은 프로퍼티 변경을 막을 수 있습니다.
const user = {
name: 'javascript'
};
const id = Symbol('id');
user[id] = 'firstId';
// 심볼은 유일한 값이라 외부에서 직접 프로퍼티에 접근할 수 없습니다.
console.log(user[Symbol('id')]); // undefined
사실 심볼로 정의한 프로퍼티를 수정할 방법이 없는 것은 아닙니다.
getOwnPropertySymbols() 메서드로 심볼 키 값을 얻어 와서 갱신할 수 있지만 일반 프로퍼티보다는 변경에 대해 안전합니다.
하지만 심볼 키 값을 통해 갱신하는 것 자체가 바람직한 사용 방법은 아니니 지양하길 바랍니다.
▷객체
자바스크립트에서 원시 타입이 아닌 모든 값은 객체입니다.
객체는 이름(키):값 형태로 여러 값을 포함하는 컨테이너이며, 컨테이너 내부의 값은 얼마든지 변경할 수 있습니다.
이름에 해당하는 프로퍼티 명은 숫자와 문자열, 심볼만 가능하며 값에 해당하는 프로퍼티의 값은 어떤 표현식이든 올 수 있습니다.
① 객체의 생성
객체를 생성하는 방법은 세 가지입니다.
Object() 생성자 함수를 이용하는 방법, 객체 리터럴({})을 사용하는 방법, 직접 정의한 생성자 함수를 이용하는 방법입니다.
- Object() 생성자 함수 사용
Object()는 객체를 생성하도록 자바스크립트에 내장된 생성자 함수입니다.
const obj = new Object();
// 프로퍼티 생성
obj.id = 'id';
obj.name = 'name';
Object() 생성자 함수를 통해 obj라는 빈 객체를 생성한 뒤 프로퍼티를 추가했습니다.
하지만 사실 이 방법은 뒤에서 설명할 객체 리터럴을 사용해 생성하는 것이 훨씬 간결하기 때문에 거의 사용되지 않는 편입니다.
- 객체 리터럴
중괄호({})를 사용해 객체를 생성하는 강력한 문법입니다.
앞서 언급했던 이름:값 형태로 프로퍼티 이름과 값을 중괄호 안에 정의해 객체를 생성합니다.
만약 중괄호 안에 어떠한 프로퍼티도 정의하지 않는다면 빈 객체가 생성됩니다.
Object() 생성자 함수가 아닌 객체 리터럴 방식을 사용하면 간결하게 객체를 생성할 수 있습니다.
const obj = {
id: 'id',
name: 'name'
};
객체 리터럴은 간단한 문법으로 객체 생성과 동시에 프로퍼티까지 추가할 수 있어 객체를 생성할 때 가장 많이 사용되는 방법입니다.
- 생성자 함수
자바스크립트에서 생성자 함수를 이용하면 동일한 형태의 객체를 쉽게 생성해서 사용할 수 있습니다.
그럼 자바스크립트에서 생성자 함수는 어떻게 만들 수 있을까요?
다른 프로그래밍 언어와는 달리 자바스크립트에서 생성자 함수는 형식이 정해져 있지 않습니다.
함수를 선언한 후 new 키워드를 사용해 호출하면 해당 함수는 생성자 함수로 동작합니다.
하지만 모든 함수를 생성자 함수로 사용하진 않습니다.
따라서 일반 함수와 생성자 함수를 구분하기 위해 생성자 함수 이름의 첫글자를 대문자로 표기하는 것을 권장합니다.
function Vehicle(type) {
this.type = type;
}
const car = new Vehicle('Car'); // {type: 'Car'}
Vehicle() 생성자 함수를 new 키워드와 함께 호출해 새로운 객체를 생성했습니다.
그리고 이 함수를 이용해 동일한 형태의 객체를 필요할 때마다 생성합니다.
자바스크립트에서는 위 코드처럼 특정한 형태의 객체를 생성하거나 상속받고 싶을 때 생성자 함수를 사용합니다.
② 객체의 프로퍼티 읽기
객체의 프로퍼티는 점 표기법 또는 대괄호 표기법으로 접근합니다.
점 표기법을 사용하면 점을 찍고 접근하려는 프로퍼티 명을 작성해 사용합니다.
만약 접근한 프로퍼티가 객체라면 하위 객체의 프로퍼티에 중첩해 접근합니다.
obj.name;
obj.age;
// 아래처럼 중첩해 하위 객체의 프로퍼티에 접근할 수 있습니다.
obj.child.name;
대괄호 표기법은 접근하려는 프로퍼티 명을 문자열 형태(정확히는 문자열로 변환되는 표현식)로 만들어 대괄호로 감싼 후 프로퍼티에 접근합니다.
obj['name'];
obj['age'];
대부분은 사용하기 간결한 점 표기법을 많이 사용하지만 대괄호 표기법을 사용해야만 프로퍼티에 접근할 수 있을 때가 있습니다.
변수를 사용해 프로퍼티에 접근하거나 접근하려는 프로퍼티 명에 연산자가 포함된 경우에는 반드시 대괄호 표기법을 사용해야 합니다.
const prop = 'name';
obj[prop];
obj['last-name'];
점 표기법과 대괄호 표기법 모두 객체에 존재하지 않는 프로퍼티에 접근한 경우 undefined 값을 반환합니다.
cons obj = { name: 'name'};
console.log(obj.age); // undefined
console.log(obj['age']); // undefined
③ 동적 프로퍼티 생성과 갱신
자바스크립트의 객체는 생성된 후에도 동적으로 프로퍼티를 추가하거나 갱신할 수 있습니다.
앞서 살펴본 점 표기법이나 대괄호 표기법을 사용해 객체의 프로퍼티를 동적으로 변경할 수 있습니다.
만약 객체에 프로퍼티가 존재하지 않는다면 새로운 프로퍼티가 추가되고, 있다면 기존 프로퍼티 값이 갱신됩니다.
- getter와 setter
앞서 우리가 살펴본 방법은 모두 객체의 프로퍼티에 직접 값을 설정하거 접근하는 것입니다.
하지만 어떤 프로퍼티에 접근할 때마다 동적인 계산이 필요하거나 프로퍼티 값이 변경될 때마다 별도의 처리 코드가 필요하다면 어떻까요?
이럴 때 getter와 setter 접근자 프로퍼티를 사용해 일반 프로퍼티처럼 사용할 수 있습니다.
접근자 프로퍼티의 값에 접근하면 getter 메서드가 호출되며 이 메서드의 반환 값이 접근 표현식의 결과값입니다.
만약 접근자 프로퍼티의 값을 변경하려고 하면 setter 메서드가 호출됩니다.
const obj = {
myNmae = 'javescript',
set name(name) {
if (name !== null) {
this.myNmae = name;
}
}.
get name() {
return this.myName;
}
}
접근자 프로퍼티를 정의하는 가장 간단한 방법은 위 코드처럼 객체 리터럴 문법을 사용하는 것입니다.
일반 프로퍼티와는 다르게 접근자 프로퍼티는 get/set 문법을 사용해 정의합니다.
getter와 setter 메서드를 보면 this 키워드를 사용합니다.
이는 메서드 안에서 this 키워드가 객체 자신을 가리키기 때문에 this.myName으로 객체의 프로퍼티에 접근할 수 있는 것입니다.
접근자 프로퍼티는 프로퍼티의 값을 갱신할 때 유효성을 검증하거나 조건에 따라 다른 값을 반환하는 작업들을 할 때 많이 사용합니다.
- Object.defineProperty()와 프로퍼티 속성
접근자 프로퍼티를 생성하는 또 다른 방법은 정적 메서드 Object.defineProperty()를 사용하는 것입니다.
이 메서드는 객체에 직접 새로운 프로퍼티를 정의하거나 이미 존재하는 프로퍼티를 수정한 후 그 객체를 반환합니다.
const obj = { myname: 'javescript' };
Object.defineProperty(obj, 'name', {
set(name) {
if (name !== null) {
this.myName = name;
}
},
get() {
return this.myName;
}
});
Object.defineProperty() 메서드는 첫 번재 인자로 대상이 되는 객체, 두 번째 인자로 추가 도는 갱신하려는 프로퍼티 명이나 심볼을 넘깁니다.
그리고 마지막 인자로 프로퍼티 서술자를 정의한 객체를 넘깁니다.
getter와 setter를 포함해 다음과 같은 프로퍼티 서술자들이 있습니다.
프로퍼티 서술자 | 설명 |
configurable | 프로퍼티의 삭제 및 서술자의 변경 가능 여부를 결정합니다. 변경 및 삭제가 가능하면 configurable 속성값은 true이며 디폴트값은 false입니다. |
enumerable | 열거 시 프로퍼티의 노출 여부를 결정합니다. 열거 시 프로퍼티가 노출된다면 enumerable 속성값은 true이며 디폴트값은 false입니다. |
writable | 프로퍼티의 수정 가능 여부를 결정합니다. 수정이 가능하다면 writable 속성값은 true이며 디폴트값은 false입니다. |
value | 프로퍼티의 값으로 디폴트값은 undefined입니다. |
get | getter 접근자 프로퍼티 메서드로 디폴드값은 undefined입니다. |
set | setter 접근자 프로퍼티 메서드로 디폴트값은 undefined입니다. |
Object.defineProperty() 메서드는 위 서술자들을 사용해 객체의 프로퍼티를 더욱 정교하게 제어합니다.
Object.defineProperty(obj, 'name', {
// name 프로퍼티의 수정을 허용합니다.
writable: true,
// name 프로퍼티의 값을 설정합니다.
value: 'myName'
});
여기까지 자바스크립의 객체와 타입에 대해 알아보았습니다 :)
'프론트엔드 > Javascript' 카테고리의 다른 글
[Javascript] ⑥ 자바스크립트 타입 변환 (0) | 2022.07.20 |
---|---|
[Javascript] ⑤ 구문과 연산자 (0) | 2022.07.19 |
[Javascript] ④ 자바스크립트 랩퍼(Wrapper) 객체 (0) | 2022.07.18 |
[Javascript] ③ 자바스크립트 배열 (0) | 2022.07.18 |
[Javascript] ① 자바스크립트 변수 선언 (0) | 2022.07.14 |
- Total
- Today
- Yesterday
- 머신러닝
- rtl
- 자바
- 프로젝트 회고
- frontend
- 리액트
- 자바스크립트
- testing
- 인프런
- jest
- 파이썬
- next.js
- Python
- CSS
- 프론트엔드 공부
- react-query
- 리액트 훅
- JSP
- react
- 프론트엔드 기초
- HTML
- 데이터분석
- styled-components
- 프론트엔드
- 자바스크립트 기초
- 딥러닝
- 타입스크립트
- 디프만
- TypeScript
- 스타일 컴포넌트 styled-components
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |