SEB[JS/Node : 핵심개념, 문법]
부트캠프 18일차가 된 날이다. 오늘은 JS/Node
의 핵심개념들과 문법들에 대해서 공부를 했다. 전에는 가볍게 알아보는 수준이었다면, 오늘은 조금 더 깊이 파고들어 학습을 하는 시간을 가졌다. 오늘 배운 개념들을 복습할 겸 정리를 시작해보겠다.
원시자료형과 참조자료형
일단 고정된 저장 공간을 차지하는 데이터는 모두 원시 타입(primitive) 데이터라고 생각하자!
원시 자료형
javascript
에서 원시 타입의 데이터는 객체가 아니면서 메소드를 가지지 않는 6가지 타입을 말한다.
string
,number
,bigint
,boolean
,undefined
,symbol
이 있는데 여기에는null
도 끼워줄 수도 있겠다. 저 6가지는typeof
를 통해 검사하면 저대로 출력이 되나null
은object
로 출력이 된다. 하지만 동작은 원시타입과 비슷하기 때문에 끼워줄 수도 있다.
-
모두 하나의 정보(데이터)를 담고 있다. 즉, 변수에는 하나의 데이터만 보관이 가능하다.
-
원시 자료형이 보관함인 변수에는 하나의 원시자료형만 들어갈 수 있다. 이는 참조자료형과 구분되는 특징히다.
참조 자료형
JS
에서 원시 자료형이 아닌 것은 모두 참조 자료형이다.
참조 자료형이 저장되는 특별한 보관함. Heap!
- 참조 자료형의 변수에는 데이터가 위차한 곳(메모리상 주소)을 가리키는 주소가 저장된다.
- heap의 크기는 동적(dynamic) 하게 변한다
- 데이터는 별도로 관리되고, 변수에는 주소가 저장되기 때문에 refernce type이라고 한다.
heap이 동적으로 크기가 변하는 이유
- 대량의 데이터가 들어오는 경우, 고정된 데이터를 사용하는 것은 비효율적이다.
- 데이터가 언제 늘어나고 줄어들지 모르기 때문에 별도의 저장공간을 마련하여 따로 관리한다.
원시 자료형과 참조 자료형의 특징
- 할당 시에 원시 자료형은 변수에 값 자체가, 참조 자료형은 주소가 담긴다.
- 원시 자료형의 보관함 크기는 고정, 참조 자료형은 동적으로 크기가 변한다.
스코프(scope)
'범위'의 의미를 가지고 있다. 더 자세하게 말하면 변수의 유효 범위라고 알면 된다.
스코프와 주요 규칙(변수의 접근 규칙)
-
변수에는 접근할 수 있는 범위가 존재한다.
여기에서는 중괄호(블록) 안에 선언됐는가, 바깥쪽에서 선언됐는가가 중요하다. 이 범위를 스코프라고 한다.- 바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용가능하다.
- 안쪽 스코프에서 선언한 변수는 바깥쪽 스코프에서 사용 불가능하다.
-
스코프의 정의와 규칙
- 변수 접근 규칙에 따른 범위
- 안쪽 스코프에서 바깥쪽 스코프로는 접근 가능하지만, 그 반대는 불가능하다
- 스코프는 중첩이 가능하다.
- 가장 바깥쪽 스코프는 전역 스코프(Global Scope) 라고 하고, 그 외에는 지역 스코프(Local Scope)라고 한다.
- 지역 변수가 전역 변수보다 더 높은 우선순위를 갖는다.
- 변수 접근 규칙에 따른 범위
스코프의 종류와 let, var, const 키워드
스코프의 종류
- 중괄호로 둘러싼 범위(block scope : 블록 스코프)
- 함수로 둘러싼 범위(function scope : 함수 스코프)
같은 함수여도, 화살표 함수 를 사용하면 블록 스코프로 취급된다. function키워드를 사용하면 함수 스코프이다. 이것이 화살표 함수와 일반 함수의 가장 큰 차이점이다.
블록스코프와 var키워드
-
let키워드는 for문 안의 변수를 바깥에서 사용하면 ReferenceError가 발생한다.
-
var키워드는 for문 안의 변수를 바깥에서 사용하면 에러가 발생하지 않는다.
-
var 키워드는 block scope를 무시하고, function scope만 따른다!
var과 let 키워드
-
변수를 정의하는 또 다른 키워드가 var이다
- var 키워드는 블록 스코프를 무시하고, 함수 스코프만 따른다.
- 블록 단위로 스코프를 구현했을 때, 훨씬 더 예측 가능한 코드를 작성할 수 있으므로, let 키워드를 사용하는 것이 좋다.
- var 키워드를 사용하지 않는다해도, 함수스코프는 let으로 선언된 변수의 접근을 제한한다.
-
var 키워드보다 let 키워드가 더 안전한 이유
- var 키워드는 재선언을 해도 에러가 없지만, let 키워드는 재선언을 방지한다
const 키워드
- 변하지 않는 값, 상수(constant) 를 정의할 때 사용한다.
- let 키워드와 동일하게, 블록스코프를 따른다
- 값의 변경을 최소화하여 보다 안전한 프로그램을 만들 수 있다. 값을 새롭게 할당할 일이 없다면 const 키워드를 사용하는 것이 좋다.
- 값을 재할당하는 경우, TypeError가 발생한다.
변수 선언에서 주의할 점
window 객체(browser only)
- var로 선언된 전역변수 및 전역함수는 window객체에 속하게 된다. window는 전역영역을 담당한다.
- 브라우저에는 window라는 객체가 존재한다.
- 브라우저 창을 대표하는 객체
- 하지만 브라우저 창과 관계없이 전역항목도 담고 있다.
- 브라우저에는 window라는 객체가 존재한다.
전역변수는 최소화 (side effect를 줄이는 것)
- 전역변수 : 어디서든 접근 가능한 변수
- 편리한 대신, 다른 함수 혹은 로직에 의해 의도되지 않는 변경이 발생할 수 있다.
let, const를 주로 사용할 것
- var은 블록스코프를 무시하며, 재선언해도 에러가 발생하지 않기 때문에, 같은 스코프에서 동일한 이름의 변수를 재선언하는 것은 버그를 유발할 수 있다.
- 전역변수를 var로 선언하는 경우 문제가 될 수 있다. var로 선언한 전역변수가 window기능을 덮어씌운다면 내장기능을 사용할 수 없게 만들 수 있다.
선언없는 변수 할당 금지
- 선언 키워드 없이 변수를 할당하면 안된다. 변수를 선언한 적이 없어도, 값을 할당하면 var로 선언된 전역 변수처럼 작동한다.
- 실수를 방지하기 위해 strict mode를 사용 가능하다. js 파일 상단에
'use strict';
를 기재하면 사용 가능하다.
클로저
- MDN 정의 : 함수와 함수가 선언된 어휘적(lexical)환경의 조합이라 한다. 하지만 이건 잘 이해가 안된다.
- 외부함수의 변수에 접근할 수 있는 내부함수라고 생각하면 더 쉽게 생각할 수 있다.
클로저 함수의 특징
- 함수를 리턴하는 함수. 이것이 클로저의 형태를 만든다.
- 외부함수의 변수에 접근가능한 내부함수이다.
따라서, 함수를 리턴하는 것만큼이나, 변수가 선언된 곳이 중요하다.
클로저의 활용
- 데이터를 보존하는 함수
- 일반적인 함수는 함수 실행이 끝나면 함수 내부의 변수를 사용할 수 없지만, 클로저는 외부함수의 실행이 끝나도 외부함수 내 변수가 메모리상에 저장된다.
-
정보의 접근 제한(캡슐화)
-
클로저 모듈 패턴
const makeCounter = () => { let value = 0; return { increase : () => { value += 1; } decrease : () => { value -= 1; } getVakye : () => value; } } const counter1 = makeCounter();
여기에서 value라는 변수에 값을 새롭게 할당할 수는 없을 것이다. 이는 스코프 규칙에 의해, 어떤 경우에도 value는 직접수정이 불가능하기 때문이다. 대신, 리턴하는 객체가 제공하는 메소드를 통해 value 값을 간접적으로 조작가능하다.
-
-
모듈화
- 재활용 가능한 makeCount 함수(위를 예시로). 여러 개의 counter를 만들 수 있다.
- 함수의 재사용성을 극대화하여, 함수 하나를 완전히 독립적인 부품형태로 분리하는 것을 모듈화라고 한다.
- 클로저를 통해 데이터와 메소드를 같이 묶어서 다룰 수 있다. 즉, 클로저는 모듈화에 유리하다.
Spread / Rest 문법
spread/rest 문법
Spread 문법
- 주로 배열을 풀어서 인자로 전달하거나, 배열을 풀어서 각각의 요소로 넣을 때 사용한다.
function sum(x,y,z) { return x + y + z; } const numbers = [1, 2, 3]; sum(...numbers); // 6을 리턴
Rest 문법
- 파라미터를 배열의 형태로 받아서 사용할 수 있다. 파라미터 개수가 가변적일 때 유용하다.
function sum(...theArgs) { return theArgs.reduce((pre, cur) => { return pre + cur; }); } sum(1,2,3); // 6을 리턴 sum(1,2,3,4); // 10을 리턴
배열에서 사용하기
-
Spread 문법은 배열에서 강력하다. 하지만 기존 배열을 변경하지 않아 immutable하다.
-
배열 합치기
let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; arr1 = [...arr1, ...arr2]; // arr1 : [0, 1, 2, 3, 4, 5]
-
배열 복사
let arr1 = [0, 1, 2]; let arr2 = [...arr1]; arr2.push(4); // arr1 : [0, 1, 2], arr2 : [0, 1, 2, 4]
-
객체에서 사용하기
let obj1 = {foo : 'bar', x : 42}; let obj2 = {foo : 'baz', y : 13}; let clonedObj = {...obj1}; // {foo : 'bar', x : 42} let mergedObj = {...obj1, ...obj2}; // {foo : 'baz', x : 42, y : 13};
함수에서 나머지 파라미터 받아오기
function myfun(a, b, ...args) { console.log('a, ' + a); console.log('b, ' + b); console.log('args, ' + args); } myfun('one', 'two', 'three', 'four', 'five'); // a, one // b, two // args, ['three', 'four', 'five'] <- 배열의 형태로
구조분해(Destructing)
구조 분해 할당은 spread 문법을 활용해서 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정이다.
-
분해 후 새 변수에 할당
-
배열
const[a, b, ...rest] = [10, 20, 30, 40 ,50]; // a : 10, b : 20, rest : [30, 40, 50]
-
객체
const{a, b, ...rest} = {a : 10, b : 20, c : 30, d : 40}; // a : 10, b : 20, rest : {c : 30, d : 40}
여기에서 const 안의 ab, cd라면 ab, cd는 undefined고, rest가 {a : 10, b : 20, c : 30, d : 40}가 된다.
-
이번 챕터와 3주차를 마치며...
이번 챕터는 JS/Node의 핵심개념과 문법에 대해 알아봤다. 분명 쉬운 부분도 있었고 어려운 부분이 존재했다. 특히 구조분해를 하는 부분에서 객체에 대한 것이었는데 잘 배웠다고 생각했는데 실습을 해보니 엉망진창이었다. 이는 내가 조금 더 보완을 해야할 것 같다. 그리고 이번 주는 css도 더 깊게 해보는 시간을 가졌는데 특히 나는 CSS로 레이아웃을 구성하는 것을 어려워했던 것 같다. 많이 사용해보지도 못했고. 뭔가 구성하는데 있어서 내가 잘 생각을 못해내는건지, 제대로 하지 않은건지 많이 어려움을 겪었다. 이번 주 챕터를 하면서 느낀 것은 내가 어려워 하는 것들은 확실히 경험해보지 못하고, 많이 사용하지 않았던 것에서 나왔었다. 그러므로 나는 이를 극복하기 위해 더 경험하고, 실습같은 것을 더 하면서 많이 사용하면서 사용방법을 익혀야 될 것 같다. 이번 주는 정말 모르는 부분이 꽤 많았던 주였다. 앞으로더 더 많이 모르는 것들이 많이 나올텐데 기죽지 말고 내껄로 잘 만들어보자..!
Reference
- 코드스테이츠(CodeStates) 강의자료
Author And Source
이 문제에 관하여(SEB[JS/Node : 핵심개념, 문법]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jogiyo/SEBJSNode-핵심개념-문법저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)