8 minute read

01장. 리액트 개발을 위해 꼭 알아야 할 자바스크립트

1.1 자바스크립트의 동등 비교

1.1.1 자바스크립트의 데이터 타입

원시타입

  • boolean
  • null
  • undefined
  • number
  • string
  • symbol
  • bigint

객체타입

  • object
  1. undefined
    선언한 후 값을 할당하지 않은 변수 또는 값이 주어지지 않은 인수에 자동으로 할당되는 값
    let foo
    typeof foo === 'undefined' // true
    function bar(hello) {
      return hello
    }
    typeof bar() === 'undefined'// true
    
  2. null
    아직 값이 없거나 비어 있는 값을 표현
    typeof null === 'object' // true
    

    typeof null을 진짜 ‘null’로 표현하고자 하는 시도가 있었으나 호환성이슈로 받아들여지지 않았다.

  3. Boolean
    참(true)와 거짓(false)만을 가질 수 있는 데이터 타입

    • falsy |값|타입|설명| |:—|:—|:—| |false|Boolean|falsy| |0,-0,0n,0x0n|Number, BigInt|0은 부호나 소수점 유무에 상관없이 falsy| |NaN|Number|faslsy| |’’, “”, ``|String|빈 문자열은 falsy| |null|null|falsy| |undefined|undefined|falsy|

    • truthy

      • 앞에서 언급한 falsy로 취급되는 값 이외에는 모드 true로 취급
      • 객체와 배열은 내부에 값이 존재하는지 여부와 상관없이 truthy로 취급
  4. Number -(253-1)과253-1 사이의 값
    const a = 1
    const maxInteger = Math.pow(2, 53)
    maxInteger - 1 = Number.MAX_SAFE_INTEGER // true
    
    const minInteger = -(Math.pow(2, 53) - 1)
    minInteger === Number.MIN_SAFE_INTEGER // true
    
    const 이진수_2 = 0b10 // 2진수
    이진수_2 == (2).toString(2) // true (2)를 괄호로 선언한 이유는 2뒤에 점이 있으면 소수점으로 인식하기 때문에
       
    const 팔진수_8 = 0o10 // 8진수(octal) 8
    팔진수_8 == (8).toString(8) // true
       
    10 == (10).toString(10) // true
       
    const 십육진수_16 = 0x10 // 16진수(hexadecimal) 16
    십육진수_16 == (16).toString(16)
    

    toString()아닌가요. 괄호안에 2가 있으니까 false가 되네요.

  5. BigInt
    • number가 두룰 수 있는 숫자 크기의 제한을 극복하기 위해 ES2020에서 새롭게 나온 것
    • 최대 253-1을 저장할 수 있는 number의 한계를 넘어서 더 큰 숫자를 저장할 수 있게 해준다. ```js 9007199254740992 === 9007199254740993 //마지막 숫자는 다릉데 true가 나온다. 이는 더 이상 다룰 수 없는 크기이기 때문

    const maxInteger = Number.MAX_SAFE_INTEGER console.log(maxInteger + 5 === maxInteger +6) // true const bigInt1 = 9007199254740995n // 끝에 ns을 붙이거나 const bigInt2 = BigInt(‘9007199254740995’) // BigInt 함수를 사용하면 된다.

    const number = 9007199254740992 const bigint = 9007199254740992n

    typeof number // number typeof bigint // bigint

    number == bigint // true number === bigint // false(타입이 달라서 false가 반환된다) ```

  6. String
    • 한 쌍의 작은따옴표(‘)나 큰따옴표(“), 또는 내장 표현식을 허용하는 문자열 리터럴 표현 방식인 백틱(`)으로 표현
    • 백틱을 사용한 템플릿 리터럴은 줄바꿈이 가능하고, 문자열 내부에 표현식을 쓸 수 있다.
      // '\n안녕하세요.\n'
      const longText=`
      안녕하세요.
      `
      // Uncaught SyntaxError: Invalid or unexpected token
      const longText = "
      안녕하세요
      "
      
    • 문자열은 원시 타입이며 변경 불가능. 한번 문자열이 생성되면 그 문자열을 변경할 수 없다. ```js const foo = ‘bar’

    console.log(foo[0]) // ‘b’

    // 앞 글자를 다른 글자로 변경해 보았다. foo[0] = ‘a’

    // 이는 반영되지 않는다. console.log(foo); // bar ```

  7. Symbol
    중복되지 않는 어떠한 고유한 값을 나타냄
    // Symbol 함수에 같은 인수를 넘겨주더라도 이는 동일한 값으로 인정되지 않는다.
    // 심벌 함수 내부에 넘겨주는 값은 Symbol 생성에 영향을 미치지 않는다(Symbol.for 제외).
    const key = Symbol('key')
    const key2 = Symbol('key')
    
    key === key2 // false
    
    // 동일한 값을 사용하기 위해서는 Symbol.for를 활용한다.
    Symbol.for('hello') === Symbol.for('hello') // true
    

    객체 타입 - 자바스크립트를 이루고 있는 대부분의 타입이 객체 타입 - 배열, 함수, 정규식, 클래스 등이 포함 - 참조를 전달한다고 해서 참조 타입으로 불린다. ```js typeof [] === ‘object’ // true typeof {} === ‘object’ // true

function hello() {} typeof hello === ‘function’ // true

const hello1 = function() {} const hello2 = function() {}

// 객체인 함수의 내용이 육안으로는 같아보여도 참조가 다르기 때문에 false가 반환된다. hello1 === hello2 // false


## 1.1.2 값을 저장하는 방식의 차이
- 값을 저장하는 방식의 차이가 동등 비교를 할 때 차이를 만드는 원인이 된다.
- 원시 타입은 불변 형태의 값으로 저장. 변수 할당 시점에 메모리 영역을 차지하고 저장
- 객체는 프로퍼티를 삭제, 추가, 수정할 수 있으므로 변경 가능한 형태로 저장, 값을 복사할 때도 값이 아닌 참조를 전달
```js
let hello = 'hello world'
let hi = hello; // 'hello world'라는 값이 hi에 복사
console.log(hello === hi) // true

var hello = { greet: 'hello, world' };
var hi = { greet: 'hello, world' };
console.log(hello === hi); // false
console.log(hello.greet === hi.greet); // 원시값인 내부 속성값을 비교하면 동일

1.1.3 자바스크립트의 또 다른 비교 공식, Object.is

  • 두 개의 인수를 받으며, 이 인수 두 개가 동일한지 확인하고 반환하는 메서드
  • Object.is이 ==나 ===와 다른 점은 다음과 같다.
    • == vs Object.is: ==는 강제형변환(type casting)을 함. Object.is는 이러한 작업을 하지 않음
    • === vs Object.is: Object.is가 좀 더 개발자가 기대하는 방식으로 정확히 비교함 ```js -0 === +0 // true Object.is(-0, +0); // fasle

    Number.NaN === NaN // false Object.is(Number.NaN, NaN) // true

    NaN === 0/0 // false Object.is(NaN, 0/0) // true

    // Object.is를 사용한다 하더라도 객체 비교에는 별 차이가 없다. Object.is({}, {}) // false const a = { hello: ‘hi’ } const b = a Object.is(a, b) // true a === b // true ```

    • Object.is는 ES6에서 새롭게 도입된 비교 문법
    • 여전히 객체 간 비교에 있어서는 자바스크립트의 특징으로 인해 ===와 동일하게 동작

1.1.4 리액트에서의 동등 비교

  • 리액트에서 사용하는 동등 비교는 Object.is다.
  • Object.is는 ES6에서 제공하는 기능이기 때문에 리액트에서는 이를 구현한 폴리필을 함께 사용한다.
    function is(x: any, y:any) {
      return (
        (x === y && (x !== 0 || 1/x === 1/y)) || (x !== x & y !== y)
      )
    }
    
    // 런타임에 Object.is가 있다면 그것을 사용하고, 아니라면 위 함수를 사용하낟.
    // Object.is는 인터넷 익스플로러 등에 존재하지 않기 때문에 폴리필을 넣어준 것으로 보인다.
    const objectIs: (x: any, y: any) => boolean = typeof Object.is === 'function' ? Object.is : is
    export default objectIs
    

1.2 함수

1.2.1 함수란 무엇인가?

작업을 수행하거나 값을 계산하는 등의 과정을 표현하고, 이를 하나의 블록으로 감싸서 실행 단위로 만들어 놓은 것을 의미

1.2.2 함수를 정의하는 4가지 방법

  1. 함수 선언문
    • 표현식(값)이 아닌 일반 문으로 분류
       // 선언문
       function add(a, b) {
       return a + b
       }
       // 표현식
       const sum = function sum(a, b) {
       return a + b;
       }
       sum(10, 24); // 34
      
    • 자바스크립트 엔진이 코드의 문맥에 따라 동일한 함수를 문이 아닌 표현식으로 해석하는 경우가 있다.
    • 위의 함수 리터럴은 코드 문맥에 따라 선언문으로도, 표현식으로도 사용될 수 있다.
  2. 함수 표현식
    • 일급객체
    • 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
    • 다른 함수의 매개변수가 될 수도 있고, 반환값이 될 수도 있음 - 함수 표현식과 선언 식의 차이
    • 함수 선언문은 함수의 호이스팅(코드 맨 앞단에 작성된 것처럼 작동하는 특징)
    • 함수 표현식은 할당한 변수만 호이스팅됨(런타임 이전에 undefined로 초기화되고, 런타임 시점에 함수가 할당되어 작동)
  3. Function 생성자
      const add = new Function('a', 'b', 'return a + b')
      add(10, 24); // 34
    
    • 생성자 방식으로 함수를 만들게 되면 함수의 클로저 또한 생성되지 않는다.
    • 생성자 함수 방식으로 함수를 만드는 것은 권장되지 않는다.
  4. 화살표 함수
      const add = (a, b) => {
     return a + b
      }
      const add = (a, b) => a + b
    
    • consturctor 을 사용할 수 없다.
    • arguments가 존재하지 않는다.
    • 함수 자체의 this 바인딩을 갖지 않습니다.
        class Component extends React.Component {
       functionCountUp() {
         console.log(this); // undefined
       }
       ArrowFunctionCountUp = () => {
         console.log(this); // class Component
       }
        }
      

1.2.3 다양한 함수 살펴보기

즉시 실행 함수

  • 함수를 저으이하고 그 순간 즉시 실행되는 함수
  • 단 한번만 호출되고 다시금 호출할 수 없는 함수
  • 글로벌 스코프를 오염시키지 않는 독립적인 함수 스코프를 운용할 수 있다는 강점
    (function (a, b) {
      return a + b
    })(10, 24); // 34
    
    ((a, b) => {
      return a + b
    })(10, 24); // 34
    

고차 함수

  • 일급객체는 함수를 인수로 받거나 결과로 새로운 함수를 반환시킬 수 있는데 이러한 역할을 하는 함수를 고차 함수라고 함.
    // 함수를 매개변수로 받는 대표적인 고차함수, Array.prototype.map
    const doubledARray = [1, 2, 3].map((item) => item * 2)
    
    doubledArray // [2, 4, 6]
    
    // 함수를 반환하는 고차 함수의 예
    const add = function (a) {
      // a가 존재하는 클로저를 생성
      return function (b) {
        // b를 인수로 받아 두 합을 반환하는 또 다른 함수를 생성
        return a + b
      }
    }
    

    고차 함수형 컴포넌트를 만들면 컴포넌트 내부에서 공통으로 관리되는 로직을 부닐해 관리할 수 있어 효율적으로 리팩터링할 수 있음. ```

    1.2.4 함수를 만들때 주의해야 할 사항

    함수의 부수 효과를 최대한 억제하라

  • 함수의 부수 효과(side-effect)란 함수 내의 작동으로 인해 함수가 아닌 함수 외부에 영향을 끼치는 것
  • 이러한 부수 효과가 없는 함수를 순수 함수라고 함.
  • 애플리케이션을 만들면서 피할 수 없는 요소지만 이러한 부수 효과를 최대한 억제할 수 있는 방향으로 함수를 설계해야 한다.

가능한 한 함수를 작게 만들어라

  • 함수당 코드의 길이가 길어질수록
  • 중첩과 콜백이 많을 수록 추적이 어려워진다.

누구나 이해할 수 있는 이름을 붙여라

1.3 클래스

배우는 이유

  • 과거 클래스형 컴포넌트를 읽기 위해
  • 함수형으로 패러다임을 바꾼 이유
  • 프로토타입 기반으로 작동하는 클래스의 원리를 이해하기 위해

1.3.1 클래스란 무엇인가?

  • 필요한 데이터나 이를 조작하는 코드를 추상화해 객체 생성을 더욱 편리하게 할 수 있다.
  • 특정한 객체를 만들기 위한 일종의 템플릿과 같은 개념
  • 객체를 만드는 데 필요한 데이터나 이를 조작하는 코드를 추상화해 객체 생성을 더욱 편리하게 할 수 있다.
    class Car {
      // 단 하나만 존재할 수 있으며, 여러 개를 사용한다면 에러가 발생
      // 생략 가능
      constructor(name) {
        // 프로퍼티란 클래스로 인스턴스를 생성할 때 내부에 정의할 수 있는 속성값을 의미
        this.name = name;
      }
      
      // 인스턴스 메서드
      // prototype에 선언되므로 프로토타입 메서드로 불리기도 한다.
      // Object.getPrototypeOf(myCar) === Car.prototype === myCar.__proto__ // true
      // Object.getPRototypeOf를 사용하는 것이 좋다.
      hook() {
        console.log(`${this.name}이 경적을 울립니다!`)
      }
    
      // 정적 메서드
      // 인스턴스가 아닌 이름으로 호출할 수 있는 메서드
      // this를 사용할 수 없지만 인스턴스를 생성하지 않아도 사용할 수 있다.
      static hello() {
        console.log('저는 자동차입니다');
      }
    
      // setter
      set age(value) {
        this.carAge = value;
      }
    
      // getter
      get age() {
        return this.carAge
      }
    }
    
    // Car 클래스를 활용해 car 객체를 만들었다.
    const myCar = new Car('자동차');
    
    // 메서드 호출
    myCar.honk();
    
    // 정적 메서드는 클래스에서 직접 호출한다.
    Car.hello()
    
    // 정적 메서드는 클래스로 만든 객체에서는 호출할 수 없다.
    myCar.hello(); // Uncaught TypeError: myCar.hello is not a function
    
    // setter를 만들면 값을 할당할 수 있다.
    myCar.age = 32;
    
    // getter로 값을 가져올 수 있다.
    console.log(myCar.age, myCar.name); // 32 자동차
    

    1.3.2 클래스와 함수의 관계

  • 클래스가 작동하는 방식은 자바스크립트의 프로토타입을 활용하는 것
  • 일종의 문법적 설탕의 역할

1.4 클로저

  • 함수형 컴포넌트의 구조와 작동 방식, 훅의 원리, 의존성 배열 등 함수형 컴포넌트의 대부분의 기술이 모두 클로저에 의존

1.4.1 클로저의 정의

  • 함수와 함수가 선언된 어휘적 환경의 조합
  • 선언된 어휘적 환경 = 변수가 코드 내부에서 어디서 선언됐는지
    function add() {
      const a = 10
      function innerAdd() {
        const b = 20
        console.log(a + b)
      }
      innerAdd() // 30
    }
    add()
    

    1.4.2 변수의 유효 범위, 스코프

  • 변수의 유효 범위를 스코프라고 한다.

전역 스코프

  • 스코프에서 변수를 선언하면 어디서든 호출할 수 있게 된다. 함수 스코프
  • var
    • 자바스크립트는 기본적으로 함수 레벨 스코프
    • {} 블록이 스포크 범위를 결정하지 않는다

1.4.3 클로저의 활용

  • 전역 스코프는 어디서든 원하는 값을 꺼내올 수 있다는 장점이 있지만, 반대로 누구든 접근할 수 있고 수정할 수 있다.
  • 리액트에서는 useState변수를 저장해 두고, useState의 변수 접근 및 수정 또한 클로저 내부에서 확인이 가능해 값이 변하면 렌더링 함수를 호출하는 등의 작업이 이루어질 것

1.4.4 주의할 점

1.4.5 정리

1.5 이벤트 루프의 비동기 통신의 이해

1.5.1 싱글 스레드 자바스크립트

1.5.2 이벤트 루프란?

1.5.3 테스크 큐와 마이크로 태스크 큐

1.5.4 정리

1.6 리액트에서 자주 사용하는 자바스크립트 문법

1.6.1 구조 분해 할당

1.6.2 전개 구문

1.6.3 객체 초기자

1.6.4 Array 프로토타입의 메서드: map, filter, reduce, forEach

1.6.5 삼항 조건 연산자

1.6.6 정리

1.7 선택이 아닌 필수, 타입스크립트

1.7.1 타입스크립트란?

1.7.2 리액트 코드를 효과적으로 작성하기 위한 타입스크립트 활용법

1.7.3 타입스크립트 전환 가이드

1.7.4 정리

질문

  1. p.50 - private이 없던 시절에는 _를 붙여 접근해서는 안된다는 코딩 컨벤션이 있긴 했지만 어디까지나 컨벤션일 뿐 기능적으로 private과 동일한 것은 아니다.

Updated:

Leave a comment