const: 상수
let: 변수
var
const age = 50;
age = 25;
console.log(age);
// TypeError: Assignment to constant variable.
let height = 150;
height = 200;
console.log(height);
> 200
자료형
자바스크립트는 동적 언어(dynamic language)이다. 즉, 정적 언어와 달리 변수를 정의할 때 자료형을 정의할 필요가 없다.
let userId;
userId = 12;
console.log(typeof userId); //number
userId = 'user1';
console.log(typeof userId); //string
자료형 종류
string, number, boolean, null, undefined, symbol, 객체
null: 값이 없음.
undefined: 정의되지 않은 값.
symbol: 고유하고 변경할 수 없는 값
객체
앞의 6개 자료형은 null, true 등 하나의 값만 담을 수 있지만 객체는 여러 속성의 모음을 저장하는 데 사용 가능하다.
const car = {
wheels: 4,
color: "blue"
};
차의 속성을 저장하는 간단한 객체이다. 각 속성은 key-value쌍으로 저장되어 있다.
key의 자료형은 string이어야하지만, value는 모든 자료형이 될 수 있으며 심지어 함수가 들어갈 수도 있다.
const car = {
wheels: 4,
color: "blue",
drive: function() {
console.log("wroom wrooom")
}
};
console.log(Object.keys(car)[1]); //color
console.log(Object.values(car)[2]); //[Function: drive]
console.log(typeof Object.keys(car)[0]); //string
car.drive(); //wroom wrooom
빈 객체 생성하기
//빈 객체를 만드는 두 가지 방법
const car = new Object();
const car = {};
두 번째 방법이 더 일반적으로 사용되고 이를 object literal이라고도 부른다.
이제 빈 객체가 생성되었으니 새 속성을 추가해보도록 하자.
const car = new Object();
const car2 = {};
car2.color = 'red';
car2.wheels = 4;
console.log(car2) //{ color: 'red' }
console.log(Object.keys(car2)[0]); //color
console.log(Object.values(car2)); //[ 'red', 4 ]
console.log(car2.color); //red
console.log(car2['wheels']) //4
위와 같이 속성에 접근하는 방법에는 점 표기법과 대괄호 표기법이 있는데 여러 단어로 이뤄진 속성인 경우는 점 표기법을 사용할 수 없다.
const car = {
wheels: 4,
color: 'blue',
"open car": true
};
console.log(car.open car); //SyntaxError: missing ) after argument list
console.log(car["open car"]); //true
또한, 변수에 저장된 키를 통해 객체의 속성에 접근한다면 무조건 대괄호 표기법을 통해 접근해야한다.
const cars = {
ferrari: "california",
porsche: "911",
bugatti: "veyron"
};
const key = "ferrari";
console.log(cars.key); //undefined
console.log(cars['key']); //undefined
console.log(cars[key]); //california
객체 복사하기
let car = {
color: 'red'
};
let secondcar = car; //car과 주소 공유(참조)
car.wheels = 4;
console.log(car); //{ color: 'red', wheels: 4 }
console.log(secondcar); //{ color: 'red', wheels: 4 }
secondcar.drive = function(){"wrroom"};
console.log(car); //{ color: 'red', wheels: 4, drive: [Function (anonymous)] }
console.log(secondcar); //{ color: 'red', wheels: 4, drive: [Function (anonymous)] }
원시 자료형과 달리 객체를 복사할 때는 참조 방식으로 주소를 저장하게된다. 따라서 원본 car 객체를 수정하면 secondcar 객체도 동일하게 수정된다.
객체를 생성할 때 const, let으로 생성하는 것의 차이가 와닿지 않아 직접 테스트를 해봤다.
const car = {
color: 'red'
};
let secondcar = car; //car과 주소 공유(참조)
car.wheels = 4;
car = { color: 'blue'}
//TypeError: Assignment to constant variable.
이렇게 car을 const로 선언하고 car에 새 객체를 할당하려고 하면 에러가 뜬다. 즉, const로 선언을 하면 car 자체가 가지는 주소값이 바뀌면 안 된다는 뜻이다. 그 외의 주소값은 동일하되 속성을 추가, 삭제, 변경하는 것은 상관이 없다.
따라서 이렇게 let으로 선언을 해야지 car의 주소값이 변경된다.
let car = {
color: 'red'
};
let secondcar = car; //car과 주소 공유(참조)
car.wheels = 4;
car = { color: 'blue'}
console.log(car); //{ color: 'blue' }
console.log(secondcar); //{ color: 'red', wheels: 4 }
secondcar.drive = function(){"wrroom"};
console.log(car); //{ color: 'blue' }
console.log(secondcar); //{ color: 'red', wheels: 4, drive: [Function (anonymous)] }
car의 주소값을 secondcar에 할당하고 이후 car에게 새로운 객체를 재할당해서 주소값을 변경하였으니 이제 더이상 car와 secondcar는 동일한 주소값을 가지지 않게된다.
let car = {
color: 'red'
};
let secondcar = car; //car과 주소 공유(참조)
console.log(car == secondcar); //true
console.log(car === secondcar); //true
항등 연산자(==)와 완전 항등 연산자(===)를 사용하든 모두 true로 반환된다.
const emptyObj1 = {};
const emptyObj2 = {};
console.log(emptyObj1 == emptyObj2);
console.log(emptyObj1 === emptyObj2);
const obj1 = {a: 1};
const obj2 = {a: 1};
console.log(obj1 == obj2);
console.log(obj1 === obj2);
위의 코드를 실행하면 모두 false가 뜬다.
그러면 저 연산자들은 뭐지?!
자바스크립트 항등 연산자
1. == (동등 연산자)
값만 비교, 타입이 다르면 형 변환 후 비교
따라서 의도치 않게 true가 나올 수 있어서 위험하다.
0 == '0' //true
false == 0 //true
null == undefined //true -> 특수하게 둘은 같다고 간주
[] == false //true -> [], '', 0 모두 false
이런 식으로 type들이 다른데 true값이 나온다.
2. === (일치 연산자)
값과 타입 모두 일치해야 true
따라서 가장 안전하고 예측 가능하기 때문에 권장되는 비교 방식이다.
3. != (부등 연산자)
==의 반대
형변환 발생
4. !== (불일치 연산자)
===의 반대
형변환 없음
1 != '1' //false
1 !== '1' //true
* 객체, 배열, 함수 비교는 모두 참조(주소) 비교이다.
위의 emptyObj1과 emptyObj2는 생긴 것은 똑같지만 서로 다른 메모리 주소에 있는 객체이다. 즉, 두 변수는 서로 다른 참조(reference)를 가리키고 있다. 따라서 ==, === 모두 false가 된다.
객체의 복사본 만들기
그렇다면 복사본은 어떻게 만드는 것일까?
const car = {
color: 'red'
};
const secondCar = Object.assign({}, car);
car.wheels = 4;
console.log(car); //{ color: 'red', wheels: 4 }
console.log(secondCar); //{ color: 'red' }
Object.assign 함수를 이용하면 된다.
첫 번째 인수 {} 는 복사본에 해당하는 객체이고 두 번째 인수는 원본에 해당하는 객체이다.
빈 객체를 복사본으로 넣고, car를 원본으로 넣었다.
이렇게 하면 서로 다른 주소를 가지고 있는 새로운 객체가 할당되어 car에 새로운 속성 wheels를 추가하여도 복사본에 영향을 미치지 않는다.