[JS] 2. Basic (2)
in JS
1. 자료형
자료형
- 목적에 따라 특별한 성질이나 정해진 범주를 갖고 있는 데이터의 종류
- 자바스크립트에서는 6가지의 원시 타입 자료형과 1가지의 객체 타입 자료형으로 구성
원시 타입(primitive type)
- Boolean : 논리적인 값으로 true, false
- null : 존재하지 않거나 유효하지 않은 주소 표시
- undefined : 선언 후 값을 할당하지 않은 변수
- number : 정수, 실수 등의 숫자, 정수의 한계는 +-2(53제곱)
- string : 빈 문자열이나 글자들을 표현하는 문자열
- symbol : 문자열과 함께 객체 property로 사용, ES6에 추가
객체 타입(object type)
- object : 두개 이상의 복잡한 개체 저장 기능
typeof
let str = "hello";
console.log(typeof str); // string
console.log(typeof undefined); // undefined
console.log(typeof 123); // number
console.log(typeof 456n); //bigint
console.log(typeof 123.123); //number
console.log(typeof true); //boolean
console.log(typeof "hello"); //string
console.log(typeof Symbol("id")); //symbol
console.log(typeof Math); //object
console.log(typeof null); //object
console.log(typeof console.log); //function
- typeof는 인수의 자료형을 반환하는 연산자
- 연산자인 typeof x와 함수인 typeof(x)로 문법 지원
boolean
let number_check = true;
let age_check = false;
let value_check = 10 > 3
console.log(value_check) //true
- boolean은 논리적인 값을 표현하는 자료형
- 참인 true와 거짓인 false, 두 가지 값만 존재
- 주로 조건문 등에서 동작 판단의 기준으로 사용
null
console.log(typeof null) // object > 하위 버전 호환성으로 object 표기
const null_check = null
console.log(null_check === null) //true
- 값이 비어 있다는 의미로 표현되는 자료형
- 존재하지 않는(nothing), 비어 있는(empty), 알수 없는(unknown) 값을 나타내는데 사용
undefined
let name;
console.log(name) //undefined
- 값이 할당되어 있지 않은 상태를 나타날 때 사용되는 자료형
- 벼눗 선언 후 초기화 하지 않는다면, undefined 로 자동 할당
number
let num1 = 123.0
let num2 = 123.456
let num3 = 1 / 0
console.log(num1 - num2) // -0.45600000000007
// 컴퓨터는 소숫점 연산을 변수의 메모리 한계로 인해 오차가 발생한다.
// Math 사용하면 이 부분을 좀 더 clear 하게 할 수 있다
console.log((num1 - num2).toFixed(3)) // 소수점 3째자리 까지로 반올림해라
console.log(num3) //Infinity
console.log(num1 / "hello") //NaN
- 정수, 부동소수점(floating point) 숫자를 표현하는 자료형
- 관련된 연산은 사칙연산이 대표적
- 일반적인 숫자 외에 Infinity, -Infinity, NaN(Not a Number) 값은 특수 숫자 값이 포함
- number에서는 2(53제곱)-1 보다 큰 값을 사용할 수 없으며, 더 큰 정수를 다루고 싶다면 bigint 자료형 사용 필요
string
let str1 = "hello"
let str2 = 'hello'
let num = 3
let str3 = `hello ${num}`
console.log(str3)
- 문자, 문자열을 표현하는 자료형
- 자바스크립트에서 문자열은 3가지 종류의 따옴표로 표현 가능
- 큰 따옴표 “”
- 작은 따옴표 ‘’
- 역 따옴표(백틱) ``
객체 타입
let user = {
name: "nahyun",
age: 25
}
console.log(typeof user) //object
console.log(typeof user.name) //string
console.log(typeof user.age) //number
console.log(user) //{ name: 'nahyun', age: 25 }
console.log(user.name) //nahyun
console.log(user.age) //25
// 객체 요소 추가
user.height = 160; //{ name: 'nahyun', age: 25, height: 160 }
console.log(user);
// 객체 요소 삭제
delete user.age; //{ name: 'nahyun', height: 160 }
console.log(user);
- 다수의 원시 자료형을 포함하거나 복잡한 개체(entity)를 표현할 수 있는 자료형
- Object() 혹은 중괄호{}를 통해 생성
- 개체는 key:value 형태로 표현하며, 접근은 object.key형태로 표현
2. obejct 복사
// user 를 수정해도 admin이 수정되고, admin을 수정해도 user가 수정된다.
// 메모리의 주소값만 복사한 것이기 때문에 같은 값들을 가리키게 된다.
let user = {
name: "nahyun",
age: 25,
};
let admin = user
console.log(admin) //{ name: 'nahyun', age: 25 }
admin.name = "jo"
console.log(admin) //{ name: 'jo', age: 25 }
console.log(user) //{ name: 'jo', age: 25 }
- object의 값을 복사할 때는 대상 전체가 아닌 object 내 주소 값만 복사되는 문제 발생
- 가리키는 대상 전체를 복사하는 방법은
얕은 복사(Shallow copy), 깊은 복사(Deep copy)
를 통해 가능
얕은 복사
let user = {
name: "nahyun",
age: 25,
};
// for loop
let admin = {}
for (let key in user) {
admin[key] = user[key]
}
// using Object
let admin = Object.assign({}, user)
// Spread Operator
let admin = { ...user } // {user.name, user.age}
얕은 복사의 문제점
let user = {
name: "nahyun",
age: 25,
sizes: {
height: 160,
weight: 50
}
};
let admin = Object.assign({}, user)
admin.sizes.weight++
--admin.sizes.height
// 얕은 복사의 문제점
console.log(admin.sizes.weight) //51
console.log(admin.sizes.height) //159
console.log(user.sizes.weight) //51
console.log(user.sizes.height) //159
- 새로운 공간을 만드는 것
- for loop
- Object.assign()
- Spread Operator
- 객체 내 또 다른 객체가 있다면 복사되지 않는다.
깊은 복사
let user = {
name: "nahyun",
age: 25,
sizes: {
height: 160,
weight: 50
}
};
// stringify: js object > string, parse: string > js object
let admin = JSON.parse(JSON.stringify(user))
admin.sizes.weight++
--admin.sizes.height
// 얕은 복사의 문제점
console.log(admin.sizes.weight) //51
console.log(admin.sizes.height) //159
console.log(user.sizes.weight) //50
console.log(user.sizes.height) //160
- 재귀 함수를 이용한 깊은 객체 복사
- JSON 객체를 이용한 깊은 복사, stirngify는 객체를 문자열로 변환하는데 이때 원본 객체와의 참조가 끊긴다.
3. 형 변환
console.log(String(123)) //123
console.log(String(1/0)) //Infinity
console.log(String(-1/0)) //-Infinity
console.log(String(NaN)) //NaN
console.log(String(true)) //true
console.log(String(false)) //false
console.log(String(undefined)) //undefined
console.log(String("hello")) //hello
console.log(typeof String(123)) //string
console.log(typeof String(1/0)) //string
console.log(typeof String(-1/0)) //string
console.log(typeof String(NaN)) //string
console.log(typeof String(true)) //string
console.log(typeof String(false)) //string
console.log(typeof String(undefined)) //string
console.log(typeof String("hello")) //string
console.log(Number("")) //0
console.log(Number("123")) //123
console.log(Number("hello")) //NaN
console.log(Number("12hello")) //NaN
console.log(Number(true)) //1
console.log(Number(false)) //0
console.log(Number(null)) //0
console.log(Number(undefined)) //NaN
console.log(parseInt("123.123")) //123
console.log(parseFloat("123.123")) //123.123
console.log(Boolean("")) //false
console.log(Boolean("123")) //true
console.log(Boolean("hello")) //true
console.log(Boolean("12hello")) //true
console.log(Boolean(true)) //true
console.log(Boolean(false)) //false
console.log(Boolean(null)) //false
console.log(Boolean(undefined)) //false
- 자바스크립트는
느슨한 타입 언어
혹은동적 타입 언어
로 변수의자료형을 명시적으로 선언할 필요가 없는 언어
- 연산자로 인한 계산이나 변수에 전달되는 값은 자동으로
암묵적
형 변환 수행 - 강제적 형 변환을 위해서는 자료형 함수를 이용해
명시적
형 변환 수행 - Number는 정수와 실수를 모두 포함하는 자료 형 변환이므로, 정수 혹은 실수의 명시적 변환은 parse 함수 사용
- 정수 변환 : parseInt(피연산자), 실수 변환 : parseFloat(피연산자)
4. 산술대입 연산자
연산자
- 프로그램에서 데이터를 처리하여 결과를 산출할 목적으로 사용되는 문자
- 연산의 대상 값은 피연산자라고 하며, 피 연산자의 개수에 따라 단항/이항/삼항 연산자의 종류 존재
- 단항 연산자 : 부호, 증감, 논리, 비트 연산자
- 이항 연산자 : 산술, 대입, 비교, 논리 연산자
- 삼항 연산자
산술 연산자
console.log(Boolean("")) //false
console.log(Boolean("123")) //true
console.log(Boolean("hello")) //true
console.log(Boolean("12hello")) //true
console.log(Boolean(true)) //true
console.log(Boolean(false)) //false
console.log(Boolean(null)) //false
console.log(Boolean(undefined)) //false
- 수학적 계산을 위해 제공되는 연산자
대입 연산자
let num1 = 123
let num2 = 456
let str1 = "hello"
let str2 = "world"
let num3 = num1 + num2 //579
let str3 = str1 + str2 //helloworld
console.log(num3)
console.log(str3)
- 계산한 결과를 하나의 변수에 저장하기 위한 연산자
복합 대입 연산자
let num = 10
let result1 = 30;
let result2 = 30;
let result3 = 30;
let result4 = 30;
let result5 = 30;
result1 += num //result1 = result1 + num
console.log(result1) //40
result2 -= num //result2 = result2 - num
console.log(result2) //20
result3 *= num //result3 = result3 + num
console.log(result3) //300
result4 /= num //result4 = result4 + num
console.log(result4) //3
result5 %= num //result5 = result5 + num
console.log(result5) //0
- 산술 연산자로 피연산자를 계산해 결과값을 한번에 대입시켜주는 연산자
증가, 감소 연산자
let num = 10
let result = num++
console.log(result) //10
console.log(num) //11
let result2 = ++num
console.log(result2) //12
console.log(num) //12
- 숫자 1만큼 증가시키거나 감소시킬 때 사용되는 연산자
- 증가엽산자: ++(피연산자), (피연산자)++
- 감소연산자: –(피연산자), (피연산자)–
5. 비교, 논리 연산자
비교 연산자
// 문자열 비교는 앞에서부터 비교, 앞이 동등하면 뒤를 비교
console.log('z' > 'a') //true
console.log('hello' < 'hi') //true
console.log('hello' >= 'helloo') // false
console.log('3' <= 30) //true
console.log(true == 1) //true
console.log(false != 123) //true
console.log(true === 1) //false
console.log(false !== 123) //true
- 좌항과 우항의 피연산자를 비교한 다음 결과값을 논리적 자료형으로 반환하는 연산자
- == 은 단순 값의 같음을 비교하는
동등 비교
, === 는 자료형까지 같음을 판단하는일치 비교
연산자 - true, false 값으로 return
논리 연산자
console.log(true || false) //true
console.log(Boolean(0 || false)) //false
console.log(Boolean(123 || false)) //true
console.log(Boolean(123 && 0)) //false
console.log(Boolean(false && true)) //false
console.log(Boolean(true && 3)) //true
console.log(!false) //true
console.log(!123) //false
- 좌항과 우항의 피연산자 간 논리 값을 연산하여 참 또는 거짓을 결과로 얻는 연산자
- 논리 연산자 :
&&(and
),||(or)
,!(not)
6. SCOPE
// global scope
let a = 1;
let b = 2;
let c = 3;
console.log(a); //1
console.log(b); //2
{
// local scope
let a = 3;
let b = 4;
let d = 5;
console.log(a); //3
console.log(b); //4
console.log(c); //3
{
// 2-level local scope
let a = 7
let b = 8
console.log(a) //7
console.log(b) //8
}
}
console.log(a); //1
console.log(b); //2
console.log(d); //ReferenceError: d is not defined
- 변수 혹은 상수에 접근할 수 있는 범위
- 모듈/함수 내 코드에서 동일한 변수 사용시 간섭을 줄이는 용도로 사용
- Global Scope 와 Local Scope 타입으로 구분
- Global Scope : 전역에 선언되어 어디에서도 접근 가능
- Local Scope(block, function level scope) : 특정 지역에 선언되어, 해당 지역 내에서만 접근 가능
- 다른 스코프에서는 같은 이름의 변수 선언 가능하다.
- block : {}로 묶인 것
- function level scope : 함수로 묶인 것
나의 회고 🤫
객체 복사에 대해 깊게 알 수 있어서 좋았다.
객체 복사를 할 때 요즘엔 항상 spread 연산자를 활용했는데 이게 얕은 복사였다는 것도 처음 알았다.
얕은 복사는 객체 내 또 다른 객체는 복사가 안된다는 것
잊지 말기!
reducer의 불변성에 다룰 때 얕은 복사 문제 때문에 immer가 나오게 된 것이 아닐까 하는 생각이 들었다. 이 부분은 조금 더 알아봐야 겠다!
앞으로는 객체 복사시 깊은 복사 방법인 JSON.parse 도 잘 활용해봐야겠다.