[Day 25] 내장 객체 및 생성자 + 브라우저 자바스크립트

내장 객체 및 생성자

JSON (JavaScript Object Notation)

  • JSON - Javascript 객체와 유사한 표기법을 사용하는 텍스트를 통해 복잡한 자료구조를 나타낸다.

  • 직렬화(Serialization) - ‘프로그래밍 언어에서 사용하는 자료구조’를 보조기억장치에 저장하거나, 혹은 네트워크를 통해 전송해야 할 일이 생기는데, 이 때 자료 구조를 그대로 저장/전송할 수 없기 때문에 저장/전송 가능한 형태로 변환하는 절차를 거쳐야 한다. 이를 직렬화라고 한다.

  • 역직렬화(Deserialization) - 직렬화된 데이터를 프로그래밍 언어에서 다시 사용할 수 있도록 변환해주는 절차를 말한다.

    // `JSON.stringify`로 직렬화를 할 수 있습니다.
    JSON.stringify({
      key: 'value',
      arr: [1, 2, 3],
      nullProp: null,
      undefinedProp: undefined // 값이 `undefined`인 속성은 직렬화 과정에서 제외됩니다.
    }); // '{"key":"value","arr":[1,2,3],"nullProp":null}'
      
    // `JSON.parse`로 역직렬화를 할 수 있습니다.
    JSON.parse('{"key":"value","arr":[1,2,3],"nullProp":null}');
    
  • JSON은 Javascript가 전혀 다른 언어다. (JSON과 Javascript 차이)

    • 속성 이름은 꼭 쌍따옴표를 둘러주어야 한다.
    • Map, Set, Date, Error, RegExp, Function, Promise 와 같이 특별한 동작방식을 가지는 객체들을 제대로 표현할 수 없다.
    • undefined, NaN, Infinity 같은 값을 표현할 수 없다.
    • 주석을 쓸 수 없다.

Date

  • Date 객체의 생성

    • new Date() - 현재 시각을 나타내는 Date 객체를 반환한다.
    • new Date(value)
      • value가 정수인 경우, 밀리초 단위의 유닉스 시간으로 간주
      • value가 문자열인 경우, 이 문자열이 나타내는 Date 객체를 반환
    • new Date(year, month, day, hour, minutes, seconds, milliseconds) - 년, 월, 일, 시, 분, 초, 밀리초를 직접 입력해서 Date 객체를 생성
      • month(월) 부분은 0부터 11까지의 range
      • month 이후의 인수는 생략 가능, day의 default는 1이고 나머지는 default 0으로 지정된다.
  • Date 객체를 JSON으로 직렬화, 역직렬화 할 때 원하는 타입의 객체로 나오지 않을 수 있다는 점을 신경써야 한다.

    • 유닉스 시간으로 변환해서 JSON 처리하면 편리하다.
  • 문자열로 변환하기

    const now = new Date();
    console.log(now.toString()); // Sun Dec 10 2017 12:49:31 GMT+0900 (KST)
    console.log(now.toLocaleString()); // 2017. 12. 10. 오후 12:49:31
    // 사용자의 지역과 브라우저 사용 언어에 따라 시간을 표시해 준다.
    console.log(now.toDateString()); // Sun Dec 10 2017
    console.log(now.toTimeString()); // 12:49:31 GMT+0900 (KST)
    console.log(now.toISOString()); // 2017-12-10T03:49:31.145Z
    // 국제표준표기법에 따라 시간을 표시해준다. (Z는 시간대, UTC를 기준으로 한다.)
    console.log(now.toUTCString()); // Sun, 10 Dec 2017 03:49:31 GMT
    
  • 시간 간격 측정하기

    • - 연산자를 사용해서 두 Date 객체 간의 시간 간격이 얼마나 되는지를 밀리초 단위로 측정할 수 있다.

    • setInterval() - 주기적(밀리초 단위)으로 함수를 실행해준다.

      const start = new Date()
          
      setInterval(() => {
        const end = new Date()
        console.log(`경과시간: ${end - start} 밀리초`)
      }, 1000)
      
  • 라이브러리 사용하기

Symbol

  • MDN - Symbol

  • ES2015에서 새로 도입된 원시 타입(Primitive Type)이다.

  • Symbol 내장 함수를 통해 새 심볼을 생성할 수 있다.

    const sym = Symbol();
    console.log(typeof sym); // symbol
    console.log(sym); // Symbol()
    
  • Symbol은 객체의 속성 이름(key)로 사용하기 위해 만들어졌다.

    • symbol을 키로 해서 객체의 value를 반환하려면

      const mySymbol = Symbol('my symbol');
          
      const obj = {
        [mySymbol]: 'hello'
      };
          
      console.log(obj); // { [Symbol(my symbol)]: 'hello' }
          
      obj[mySymbol]	// 'hello'
      obj.mySymbol	// undefined
      
    • 내장 심볼을 객체의 속성 키로 사용하면, 특정 상황에서의 객체 동작 방식을 마음대로 바꿀 수 있다. (객체의 기능을 확장할 수 있다는 장점을 갖는다!!)

      • Symbol.iterator

        const arr = [1, 2, 3]
              
        // 배열 뿐만 아니라 iterable 객체를 순회할 때에도 사용할 수 있다.
        for(const item of arr) {
          console.log(item)
        }
        console.log(arr[Symbol.iterator])
              
        // iterable 객체란, Symbol.iterator 속성에 특별한 형태의 함수가 들어있는 객체를 말한다.
              
        for(const char of 'hello') {
          console.log(char)
        }
              
        console.log('hello'[Symbol.iterator])
              
        // 객체의 Symbol.iterator 속성에 함수를 지정하면 순회가 불가능한 객체도 순회할 수 있다.(iterable)
        const obj = {
          [Symbol.iterator]: function* () {
            yield 1
            yield 2
            yield 3
          }
        }
              
        for(const item of obj) {
          console.log(item)
        }
        

Map

  • 객체와 유사하게 키-값 쌍(key-value pair)을 저장할 수 있는 새로운 자료구조이다. (new feature in ES2015)

    const m = new Map();
      
    m.set('hello', 'world');
    console.log(m.get('hello')); // 'world'
    console.log(m.has('hello')); // true
      
    m.delete('hello');
    console.log(m.get('hello')); // undefined
    console.log(m.has('hello')); // false
    
  • Map 생성자로 생성된 객체와 일반 객체의 차이점

    • 객체는 속성 접근자(property accessor) 문법을 통해서, Map은 메소드를 통해서 내부의 데이터를 조작한다.
    • 객체의 키로는 문자열과 심볼만 사용 가능하지만, Map은 어떤 값이라도 객체의 키로 사용할 수 있다.
      • 심지어, Map의 키에 객체를 사용할 수도 있다.
    • 일반 객체의 데이터는 프로토타입의 영향을 받지만, Map 객체 안에 들어있는 데이터는 프로토타입의 영향을 받지 않는다.
    • Map 객체의 size 속성을 통해 내부에 들어있는 데이터의 개수를 쉽게 알 수 있다.
      • 일반 객체의 데이터 개수를 알려면 Object.keys(obj).length
  • Map 객체의 특징

    • 데이터의 추가/삭제가 빈번하게(1초에 10,000번 이상) 일어나는 경우 일반적인 객체보다 훨씬 빠르게 동작한다.
    • JSON 등으로 직렬화하기 어렵다.
    • key-value 형태의 데이터를 다루면서 속도가 중요한 경우 Map을 사용하면 유용하다.

Set

  • 집합 형태의 자료구조이다. (new feature in ES2015)

  • 특징

    • Set 객체는 내부에 중복된 데이터가 저장되는 것을 허용하지 않는다. (이미 존재하는 데이터를 추가하려고 하면, 무시된다.)
    • 배열과 유사한 형태의 자료구조가 필요하지만 순서가 중요하지 않은 경우, 그리고 중복된 데이터의 저장을 허용하지 않아야 할 경우 사용할 수 있다.
  • 사용 예시

    const s = new Set();
      
    s.add(1);
    s.add(1);
    s.add(2);
      
    console.log(s); // Set { 1, 2 }
    
    // set을 이용한 배열의 중복된 요소 제거
    function removeDuplicates(arr) {
        const set = new Set(arr)
        return Array.from(set)
    }
    removeDuplicates([1, 2, 3, 2, 1])	// [1, 2, 3]
    

기타 내장 객체 및 생성자들 (in ES2015)

  • Proxy - 다른 객체처럼 행세하면서, 특정한 행동에 대해서는 다른 동작방식을 보이는 새로운 객체를 만들고 싶을 때 사용한다.
  • Reflect - Reflect 객체의 메소드를 통해, 자바스크립트의 몇 가지 내장 기능을 메소드로 사용할 수 있다.
  • Intl - Intl 객체를 이용하면, 사용중인 언어에 따라 문자열 비교, 숫자 표현 형식, 시간 표현 형식을 바꿀 수 있다.
  • WeakMap - Map 생성자와 사용법이 같지만, 키로 사용된 값에 대한 메모리 누수를 방지할 수 있다.
  • WeakSet - Set 생성자와 사용법이 같지만, 집합에 추가된 값에 대한 메모리 누수를 방지할 수 있다.
  • TypedArray - 이진 데이터(binary data)를 다룰 수 있는 방법을 제공한다.
    • File API, Canvas, Fetch API 등에서 사용된다.

브라우저 자바스크립트

이벤트 리스너

  • el.addEventListener(eventName, callback) - 이벤트 리스너 등록
  • el.removeEventListener(eventName, callback) - 이벤트 리스너 제거
    • callback 부분에 익명함수가 들어가면 이벤트를 뗄 수 없기 때문에 바깥 스코프에서 callback 함수를 정의한 뒤 함수 이름만으로 사용해야 한다.

DOM 엘리먼트 생성하기

  • document.createElement(tagName) - 새로운 엘리먼트 객체 생성하기
    • html 문서에 들어가지는 않은 채로 메모리에만 떠 있는 상태이다.
  • el.cloneNode() - 엘리먼트 복사하기

DOM 트리 조작하기

  • el.appendChild(newChild) - 요소 끝에 자식 요소를 삽입하기
    • 이미 문서에 존재하는 객체를 인수에 넣어서 호출하면 그 요소객체를 복사하지 않고 위치만 이동시킨다.
  • el.insertBefore(newChild, beforeWhat) - 원하는 위치에 자식 요소를 삽입하기
    • beforeWhat에 null 을 넣으면 appendChild 처럼 요소 끝에 자식을 넣는다.
    • 이미 문서에 존재하는 객체를 인수에 넣어서 호출하면 그 요소객체를 복사하지 않고 위치만 이동시킨다.
  • el.replaceChild(newChild, oldChild) - 자식 요소를 교체하기
  • el.removeChild(child) - 자식 요소 제거하기

dataset

  • el.dataset - data-* 어트리뷰트를 가져오기.
    • kebab-case가 camelCase로 변환됨

노드 간 관계

  • el.childNodes - 자식 노드
  • el.firstElementChild - 첫 번째 자식 요소
  • el.lastElementChild - 마지막 자식 요소
  • el.previousElementSibling - 이전 형제 요소
    • 이전 형제가 없을 때 가장 마지막 형제를 선택하게 되는 이유는?
      • previousElementsSibling 속성은 이전 형제 요소가 없을 경우 null을 return 한다.
      • insertBefore 메소드의 두 번째 인자에 null이 들어가면 해당 element를 부모 요소의 맨 마지막 자식 요소로 넣는데, 기존에 문서 안에 존재하는 요소를 insertBefore로 넣을 경우 위치만 이동시킨다. 그래서 맨 마지막 자식 요소로 추가 된다.
  • el.nextElementSibling - 다음 형제 요소
    • 다음 형제가 없을 때 console에서 에러를 뿜는 이유는?
      • nextElementsSibling 속성은 다음 형제 요소가 없을 경우 null을 return 한다.
      • 다음 형제 요소가 없을 경우 null을 return 하는데 null 요소의 nextElementSibling을 찾으려고 하면 당연히 없기 때문에 에러를 뿜는다.
  • el.parentElement - 부모 요소
  • el.offsetParent - 포지셔닝의 기준이 되는 조상 요소

요소의 크기 및 위치

  • el.getBoundingClientRect() - 화면 좌측 상단으로부터의 요소의 위치 및 요소의 크기를 반환
  • el.offsetHeight / el.offsetWidth - border를 포함한 요소의 크기
  • el.clientHeight / el.clientWidth - border를 제외한 요소의 크기
  • el.scrollHeight / el.scrollWidth - 요소 내부에 포함된 콘텐츠의 크기 (스크롤 가능한 영역의 크기)
  • el.offsetTop / el.offsetLeft - offsetParent 로부터의 요소의 위치
  • el.scrollTop / el.scrollLeft - 요소 내부의 콘텐츠가 스크롤된 정도
  • el.clientTop / el.clientLeft - border의 너비

이벤트 객체

  • e.target - 실제로 이벤트를 일으킨 요소
  • e.currentTarget - 이벤트 전파 과정 중 현재 이벤트가 위치한 요소
  • e.stopPropagation() - 이벤트 전파 과정을 멈추기
  • e.preventDefault() - 이벤트가 일으키는 브라우저의 기본 동작과정을 취소하기

이벤트 전파

이벤트 전파

  • 이벤트는 흘러 다닌다. (바깥에서부터 들어와서 타겟을 거쳐서 밖으로 다시 빠져 나간다.)
  • 바깥쪽 요소에서부터 이벤트 리스너를 찾으면서 들어올 때 캡처링
  • 이벤트 발생 요소에서부터 바깥으로 이벤트 리스너를 찾으면서 나갈 때 버블링
    • 그냥 이벤트 리스너를 설정하면 캡처링 과정을 지나서 버블링 과정에서 이벤트가 발생한다.

댓글남기기