TIL 9일차 - [JS/Node] 핵심 개념과 주요 문법

🎇 Achievement Goals 🎇

⚽ 원시 자료형과 참조 자료형

  • 원시 자료형과 참조 자료형의 차이를 이해하고, 각자 맞는 상황에서 사용할 수 있다.

    원시 자료형은 값(value)을 저장하고 참조 자료형은 주소(reference)를 저장한다.

    • 원시 자료형 : number, string, undefined, boolean, bigInt, symbol, (null)
    • 참조 자료형 : 배열, 객체
  • 원시 자료형이 할당될 때에는 변수에 값(value) 자체가 담기고, 참조 자료형이 할당될 때는 보관함의 주소(reference)가 담긴다는 개념을 코드로 설명할 수 있다.
    
    let num1 = 1;
    let num2 = num1;
    num1 = 3;
    console.log(num2); // 1
    console.log(num1); // 3

    원시 자료형에는 값 자체가 할당되기 때문에 num1에 3을 할당해도 num2의 값은 바뀌지 않는다.

    
    let arr1 = [1, 2, 3];
    let arr2 = arr1;
    arr2[2] = 6;
    console.log(arr1[2]); // 6

    참조 자료형에는 주소 값이 할당되기 때문에 arr1arr2는 같은 주소를 공유하게 된다. 따라서 둘 중 하나의 값이 바뀌면 나머지 하나의 값도 바뀐다.

  • 참조 자료형은 기존에 고정된 크기의 보관함이 아니라, 동적으로 크기가 변하는 특별한 보관함을 사용한다는 것을 이해할 수 있다.

    c언어의 malloc과 비슷한 개념이다.

🥎 스코프

  • 스코프의 의미와 적용 범위를 이해할 수 있다

    스코프(Scope)는 변수의 접근 규칙에 따른 유효성 범위를 뜻한다.

    
    let username = 'kimbob';
    if (username) {
        let message = `Hello, ${username}!`;
        console.log(message); // Hello kimbob!
    }
    console.log(message); // ReferenceError

    여기서 중괄호{ }로 둘러쌓인 부분을 안쪽 스코프, 바깥을 바깥쪽 스코프라고 한다. 바깥쪽 스코프에서 선언된 변수는 안쪽 스코프에서 사용할 수 있지만, 안쪽 스코프에서 선언된 변수는 바깥에서 사용할 수 없다. 이것이 바로 유효성 범위이다. 자세한 내용은 아래를 살펴보자.

🎀 스코프의 주요 규칙 🎀

  • 중첩 규칙

    스코프는 중첩이 가능하다 !

  • Block scope와 Function scope

    스코프에는 두 가지 종류가 있다. 블록 스코프(block scope)는 중괄호{ }로 둘러싼 범위이고, 함수 스코프(function scope)는 함수로 둘러싼 범위이다. (❗ 화살표 함수는 블록 스코프에 포함된다.)

  • 전역 스코프와 지역 스코프

    스코프 중 가장 바깥쪽의 스코프를 우리는 특별히 전역 스코프(global scope)라고 부른다. 그 외의 스코프는 지역 스코프(local scope)라고 부른다.

  • 전역 변수와 지역 변수간의 우선 순위

    지역 변수는 전역 변수보다 더 높은 순위를 갖고있다.

    
    let greeting = 'Hello';
    let greets = () => {
        let greeting = 'Bonjour!';
        console.log(greeting); // Bonjour!
    }

    여기서 function 속의 greeting은 지역 변수이다. 따라서 console.log(greeting)에 출력되는 내용은 지역 변수 greeting의 값인 'Bonjour!'가 된다.

  • let, const, var 의 차이

    변수를 선언할 수 있는 키워드에는 세 가지가 있다.

    • var : 블록 스코프를 무시하고 함수 스코프만 따른다.(화살표 함수 포함)
    • let : 블록 스코프, 함수 스코프 모두 따른다. 재선언을 방지하기 때문에 블록 단위 예측이 가능하다.
    • const : 상수(constant) 역할을 한다. 값의 변경이 불가능하다. 값을 재할당 할 경우 TypeError 가 발생한다. 안전한 프로그램을 만들기 위해서는, 변수에 값을 재할당할 핗요가 없다면 const 키워드를 사용하여 선언 해주는 것이 좋다.
  • 전역 객체(window)의 이해

    브라우저에만 존재하는, 브라우저 창을 의미한다. 하지만 전역 영역을 담고 있기도 하다. var로 선언한 변수나 함수가 포함된다.

    
    var vegetable = 'carrot';
    console.log(window.vetgetable); // carrot

    때문에 전역 변수를 var로 선언할 경우 window가 망가질 수도 있다 !

🏀 클로저

  • 클로저 함수의 정의와 특징에 대해서 이해할 수 있다

    클로저(closure)란, 함수와 함수가 선언된 어휘적 환경(변수 및 함수 선언의 형태)의 조합이다. 클로저 함수는 외부 함수의 변수에 접근이 가능한 내부 함수를 일컫는다.

    
    const adder = function(x) {
       return function(y) {
       	return x + y;
       }
    }

    여기서 외부 함수는 리턴 값이 함수 형태이며, 내부 함수는 외부 함수의 x값에 접근할 수 있다.

  • 클로저가 갖는 스코프 범위를 이해할 수 있다

    리턴하는 함수(내부 함수)의 스코프는 외부 함수에 접근할 수 없다. 이를 '스코프를 이용하여 변수의 접근 범위를 닫는다' 고 이야기한다.

  • 클로저를 이용해 유용하게 쓰이는 몇 가지 코딩 패턴을 이해할 수 있다

    1) 데이터를 보존하는 함수
    위에서 이야기 했듯이, 내부 함수는 외부 함수의 변수에 접근이 불가능하다. 때문에 이를 이요하면, 외부 함수의 변수 값을 보존하며 함수를 사용할 수 있다. 위에서 쓴 adder 함수를 예로 들어보자.

    
    const add5 = adder(5);
    add5(7); // 12
    add5(18); // 23

    외부 함수 adder의 실행이 끝나더라도, 변수 x의 값은 변하지 않았기 때문에 계속 사용이 가능하다 ! 이는 태그를 만들 때 유용하게 쓰인다.

    2) 정보의 접근 제한

    
    function makeCounter() {
      let privCounter = 0;
      return {
        increment: function(){
          privCounter++;
        },
        decrement: function(){
          privCounter--;
        },
        getValue: function(){
          return privCounter;
        }
      }
    }

    위 함수는 은 클로저의 모듈 패턴이다. 외부 함수는 함수 여러 개를 포함한 '객체'를 반환한다. 이 경우 makeCounter 함수를 바꾸지 않고는 value 값을 조정할 수 없다. 이를 정보의 접근 제한(캡슐화)이라고 이야기한다.

    3) 모듈화
    함수의 재사용을 극대화하여 함수 자체를 독립적인 부품 형태로 분리한다. 데이터와 메소드를 같이 묶어서 다룰 수 있다.

🏐 Spread/Rest 문법

  • Spread 문법

    배열을 풀어서 인자로 전달하거나, 배열을 풀어 각각의 요소로 넣을 때 사용한다.

    
    function sum(x, y, z) {
        return x + y + z;
    }
    const numbers = [1, 3, 5];
    sum(...numbers); // 9
  • Rest 문법

    파라미터를 배열의 형태로 받아서 사용한다. 파라미터 개수가 가변적일 때 유용하다.

    
    function sum(...theArgs) {
        return theArgs.reduce((previous, current) => {
        	return previous + current;
        });
    }
    sum(1, 2, 3) // 6
    sum(1, 5, 6, 8) // 20

    이를 활용하여 배열과 객체를 합치고 복사하는 것이 가능하다. 함수에서 나머지 파라미터를 받아올 때도 유용하게 사용된다.

  • 구조 분해 할당

    구조 분해 (Destructing) : Spread 문법으로 값을 해체할 후 개별 값을 변수에 새로 할당 해주는 것을 이야기한다. (분해 후 새 변수에 할당)

    
    const [a, b, ...rest] = [1, 2, 3, 4, 5, 6, 7];
    a; // 1
    b; // 2
    rest; // [3, 4, 5, 6, 7]

📛 Extra Study 📛

  • Shallow copy(얕은 복사) VS Deep copy(깊은 복사)

    얕은 복사 : 참조(주소)값의 복사 ➡ 한 데이터를 공유하는 것
    깊은 복사 : 값 자체의 복사 ➡ 독립적인 메모리에 값 자체를 할당하여 생성하는 것

    ex)

    • 원시 자료형 : 깊은 복사
    • 참조 자료형 : 얕은 복사
    • Object.assign : 깊은 복사(객체 제외)
    
    const obj = {
        john: 'apple';
        charlie: 'banana';
        else :  {jane: 'peach', tom: 'kiwi', sarah: 'pineapple'}
    }
    const copiedObj = Object.assign({}, obj);

    위 함수에서 johncharlie는 깊은 복사가 되지만, else는 얕은 복사가 되어 objcopiedObj는 같은 주소를 공유하게 된다.

    • 구조 분해 병합으로 생선된 객체 : 깊은 복사(객체 제외)

오늘 너무 많은 정보를 한 번에 머리에 쑤셔 넣어서 뇌가 아주 꾸깃 꾸깃 해졌다. 그래도 TIL 작성하면서 다시 좀 예쁘게 펴진 것 같다. 내일 일어나서 한번 더 보면 더 예쁘게 펴지겠지 ! 오늘도 고생했다 나 자신 🧚‍♀️

좋은 웹페이지 즐겨찾기