[기타]

1. Eval : 문자열 코드 실행하기

문자열을 코드로 읽어와 실행시킨다. 사용예시

  let code = 'alert("Hello")';
  eval(code); // Hello

문자열 코드의 경우 해당 코드의 실행 결과가 eval의 결과가 됨

  • eval 은 렉시컬 환경에서 실행되므로 외부 변수에 접근이 가능하다.
      let a = 1;
      function f() {
    let a = 2;
    eval('alert(a)'); // 2
      }
      f();
    
  • 또는 기존 변수를 변경하는 것도 가능하다.

  • ‘eval’ 사용하기 eval은 모던 프로그래밍에서 잘 사용되지 않는다. 동적처리가 자바스크립트에서 가능해졌기 때문임.

내부적으로 eval을 실행하는 과정에서 코드 압축기를 거쳤다가 변수명이 간단하게 a,b같이 간단하게 변경하게 되는데 eval 안에서 그걸 지역변수로 받아들이면 에러가 뜰 수도 있다는데 정확하게 어떤건지는 모르겠다. 암튼 위험하다는 것이다.

2. 커링

커링이란 f(a,b,c) 인수 여러개 가진 함수를, f(a)(b)(c) 단일 프로세스로 호출한 후 병합한다는 개념이다. 예시는 다음과 같다.

  function curry(f) { // 커링 변환을 하는 curry(f) 함수
    return function(a) {
      return function(b) {
        return f(a, b);
      };
    };
  }
  // usage
  function sum(a, b) {
    return a + b;
  }
  let curriedSum = curry(sum);
  alert( curriedSum(1)(2) ); // 3

동작 1) curriedSum(1) 호출 되면 인수 1은 렉시컬 환경에 저장 되고 function(b)가 반환됨. 2) function(b)의 인수가 2로 호출되고 렉시컬 환경에서 인수들을 읽어와 sum(1,2)를 호출하게 된다.

loadash 라이브러리의 _.curry 같이 래퍼를 반환할 때 함수가 보통 때처럼 또는 partial 적으로 호출하는 것을 허용하는 기술이 있음 사용예

  function sum(a, b) {
    return a + b;
  }
  
  let carriedSum = _.curry(sum); // lodash 라이브러리의 _.carry 사용
  
  alert( carriedSum(1, 2) ); // 3, 보통 때 처럼 호출가능
  alert( carriedSum(1)(2) ); // 3, partially 호출되었음

커링 적용해서도, 아니면 기존 방식으로도 모두 사용가능함.

  • 커링은 어디에 쓰이는가 예를들어 로그 함수 log(date, importance, message) 가 있다고 할 때. 위 함수는 로그를 보내는 기능을 하는 함수이다. alert 창을 이용해서..
      function log(date, importance, message) {
    alert([${date.getHours()}:${date.getMinutes()}] [${importance}] ${message});
      }
    

    위와 같이 구현할 수 있다.

위 함수에 커링을 적용하면

  log = _.curry(log);
  log(new Date(), "DEBUG", "some debug"); // log(a, b, c)
  log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)

둘다 정상 작동한다.

그러면 다음과 같이 어떤 시간을 고정해서 출력해주는 함수를 만들 때 사용할 수 있다.

  let logNow = log(new Date());
  logNow("INFO", "message"); // [HH:mm] INFO message

: 현재시간을 출력해주는 함수를 구현 가능

  • 고급 커리 구현 다중인수를 허용하는 “고급”커리 사용예시 ```javascript // func 이 변환되어야 하는 함수입니다 function curried(…args) { if (args.length >= func.length) { // (1) 인수의 갯수가 함수의 갯수와 같거나 많을 경우 return func.apply(this, args); // 그대로 함수에 입력 } else { return function pass(…args2) { // (2) 인수의 갯수가 적을 경우 pass 래퍼 함수 출력 return curried.apply(this, args.concat(args2)); // 이전 인수와 합침 } } };

function sum(a, b, c) { return a + b + c; } let curriedSum = curry(sum); alert( curriedSum(1, 2, 3) ); // 6, 보통때 처럼 단일 callable 형식으로 호출하기 alert( curriedSum(1)(2,3) ); // 6, 첫 번째 인수를 커링하기 alert( curriedSum(1)(2)(3) ); // 6, 모두 커링하기

  1) 첫번째 curried(1) 을 호출할 때 1을 렉시컬 환경에 기억하고 curried(1)이 pass 래퍼를 반환함.
  2) pass 래퍼가 인수 (2) 와 함께 호출되고, 이전 인수 (1)을 가져와서 (2) 와 연결한 후 curried(1,2)로 만든다. 다시 pass 호출
  3) pass 래퍼가 다시 (3) 과 함께 호출됨. 다음 호출인 pass(3) => curried(1,2,3) 호출.

3. 참조타입
  복잡한 상황에서 메서드 호출 시 this 값을 잃어버리는 경우가 생김
```javascript
  let user = {
    name: "John",
    hi() { alert(this.name); },
    bye() { alert("Bye"); }
  };
  user.hi(); // John (간단한 호출은 의도한 대로 잘 동작합니다.)
  // name에 따라 user.hi나 user.bye가 호출되게 해봅시다.
  (user.name == "John" ? user.hi : user.bye)(); // TypeError: Cannot read property 'name' of undefined

user.hi()에선 잘 동작하는데 (user.hi)()에선 이상 동작함

  • 참조 타입 자세히 알아보기
    • 점은’.’ 객체 프로퍼티 obj.method 에 “접근”한다.
    • 괄호()는 접근한 프로퍼티 (메서드)를 “실행”한다. 접근과 실행의 차이.

참조 타입은 . 연산에서 알아낸 정보를 괄호()로 전달해주는 ‘중개인’ 역할임 함수를 호출했을 때만 this 값이 의도한대로 전달 됨.

  1. BigInt
    길이의 제약 없이 정수를 다룰 수 있게 해주는 숫자형.
    • 정수 리터럴 끝에 n을 붙임
    • BigInt() 안에 사용하여 문자열, 숫자열을 BigInt 값으로 만든다.
  • BigInt 형의 연산은 BigInt값을 반환해야 함.
    일반 숫자와 같이 연산처리는 안되며, 일반 숫자와 같이 쓰고 싶은 경우 BigInt()를 사용하여 형변환 해줘야 함.
  • 비교연산자 비교연산자는 BigInt 와 일반 숫자 같이 사용 가능하다.
    • ”==” “===” 의 차이를 알아야 한다.
      alert( 1 == 1n ); // true
      alert( 1 === 1n ); // false
      
  • 논리연산 0n은 false임. ||, && 등의 논리 연산자를 bigint에 적용할 때도 일반 숫자와 유사하게 동작

CHAPTER 2 브라우저: 문서, 이벤트, 인터페이스

[문서]

1. 브라우저 환경과 다양한 명세서

자바스크립트가 돌아가는 플랫폼을 “호스트”라고 한다. 브라우저도 서버도 “호스트”가 될 수 있다.

  • window (전역 객체) 웹브라우저가 호스트 환경일 때. window라는 루트 객체 아래에 수많은 객체들이 있다. window 객체의 역할은 다음과 같다. 1) 전역 객체의 역할이다. 2) ‘브라우저 창’을 대변하고 그를 제어할 수 있는 메서드를 제공한다.

  • 문서 객체 모델(DOM) DOM 은 Document Object Model 페이지 내의 모든 콘텐츠를 객체로 나타내줌. 이 객체는 수정이 가능함! 페이지의 기본 ‘진입점’ 역할을 하게 됨

사용예시

  // 배경을 붉은색으로 변경하기
  document.body.style.background = "red";
  // 1초 후 원상태로 복구하기
  setTimeout(() => document.body.style.background = "", 1000);

위의 코드를 사용하면 페이지의 배경화면을 바꿀 수 있는 것이다.

  • 브라우저 객체 모델 (BOM) Browser Object Model , 문서 이외의 모든 것을 제어. 예시 :
    • navigator : 브라우저와 운영체제에 대한 정보를 제공함. navigator.userAgent(브라우저 정보를 알려줌), navigator.platform(운영체제 정보를 알려줌)
    • location : 현재 url 을 읽을 수 있게 해주고 새로운 url로 변경 (redirect) 할 수 있음 location 사용예시)
      alert(location.href); // 현재 URL을 보여줌
      if (confirm("위키피디아 페이지로 가시겠습니까?")) {
      location.href = "https://wikipedia.org"; // 새로운 페이지로 넘어감
      }
      

      alert/confirm/prompt 이런 애들도 BOM 의 일부임. 문서와 직접 연결되어 있지 않아도 사용자-브라우저 사이의 커뮤니케이션을 도와줌.

  1. DOM 트리 HTML은 결국 태그들로 이뤄져있음
    • 문서 객체 모델(DOM) 에 따르면 HTML 태그도 객체임! 태그 하나가 감싸고 있는 애를 ‘자식 태그’,’중첩 태그’ 라고 부름
    • 태그 내의 문자 (text) 역시 객체임.

위의 모든 객체는 자바스크립트를 통해 접근이 가능함.

  document.body 는 <body> 태그를 나타냄
  그리고 document.body 안에 태그들을 받아서 html 속성을 바꿔줄 수 있다.
  • DOM 예제 다음과 같은 HTML문서가 있다고 하자. ```html <!DOCTYPE HTML>
사슴에 관하여 사슴에 관한 진실.
  위의 문서를 분석해보면
  태그 하나를 요소 노드라고 부르고 노드는 객체이다.
  또한 이 노드들은 트리구조를 형성한다.

  HTML 은 루트 노드이며
    => head
    => body 위 두개는 자식노드가 된다.
  또한 요소 내의 문자 text 노드가 된다.
  text 노드의 경우 문자열만 담으며 자식 노드는 없음. 트리의 끝노드에 해당함
  * text 노드에는 새로운 줄과 공백도 특수문자로 담고 있다는 것을 유의해야 한다!

  - 자동교정
    DOM 생성 과정에서 html을 자동으로 교정해준다.
    만약 html 파일에 텍스트만 입력한 경우에는 
    html
      => head
      => body
        => text
    이렇게 만들어버린다.

    혹은 짝이 안맞으면 자동으로 닫아준다.

    table 태그엔 반드시 tbody를 만들어준다.

    - 기타 노드 타입
    주석도 노드가 된다.

    * 노드 타입은 총 열두 가지 인데, 실무에선 주로 다음 네 가지 노드를 사용
      1) DOM의 '진입점'이 되는 문서(document) 노드
      2) HTML 태그에서 만들어지며, DOM 트리를 구성하는 블록인 요소 노드(element node)
      3) 텍스트를 포함하는 텍스트 노드(text node)
      4) 화면에 보이지는 않지만, 정보를 기록하고 자바스크립트를 사용해 이 정보를 DOM으로부터 읽을 수 있는 주석(comment) 노드

    - DOM 구조 직접 보기
      CTRL+SHIFT+C 를 사용해서 문서의 요소 확인하기

3. DOM 탐색하기
  뭐든지 일단 DOM 객체에 접근한 후 조작해야한다.
    DOM 노드 간의 관계 정리
```html
                document
                  ▼
                document.documentElement   <HTML>
                  ▼
                document.body
                  ▼
                ...
                  ▼
                parentNode
                  ▼
previousSibling◀<DIV>▶nextSibling
                  ▼
                childnodes (firstChild, lastChild)
  
  - 트리 상단의 documentElement와 body  
    <html> = document.documentElement 
    <body> = document.body
    <head> = document.head
  • childNodes, firstChild, lastChild로 자식 노드 탐색하기 자식노드와 후손노드를 구분해야 한다.
    • 자식노드 (child node, children) 바로 아래의 자식요소. 부모 바로 아래서 중첩 관계를 만듬
    • 후손노드 (descendants) 는 중첩 관계에 있는 모든 요소를 의미함. 자식노드의 자식노드까지 다 후손노드라 할 수 있음
    • childNodes 컬렉션 안에는 텍스트 노드를 포함한 모든 자식노드가 들어 있다.
    • firstChild와 lastChild 프로퍼티를 이용하면 첫번째, 마지막 자식 노드에 빠르게 접근이 가능하다.
  • DOM 컬렉션 childNodes 는 배열이 아닌 이터러블(유사 배열 객체) 컬렉션임! 그러므로 다음과 같은 특징이 있다. 1) for.. of 로 순회할 수 있다.
    for (let node of document.body.childNodes) {
      alert(node); // 컬렉션 내의 모든 노드를 보여줍니다.
    }
    

    1) 배열이 아니기 때문에 배열 메서드는 쓸 수 없다. (filter 같은 거..) 이 경우 Array.from() 을 사용하여 감싸주면 배열로 바꾸어 쓸 수 있다.

    • DOM 컬렉션은 읽기만 가능하다. 변경은 불가능
    • DOM 은 동적이라 해야하나.. 그니까 변경되면 그 상태를 그대로 반영함.
    • 컬렉션의 경우 for of 는 키 값을 기반으로 순회하는데 for in을 쓰면 모든 키값을 다 순회하기 때문에 for in은 안쓰는게 좋다.
  • 형제와 부모노드 같은 부모를 가지는 경우 형제 노드라고 부른다.
    • head와 body는 대표적인 형제 노드임. body는 head의 next (프로퍼티로는 nextSilbling) head는 body의 previous (프로퍼티로는 previousSilbling)
  • 요소간 이동 노드에 Element 라는 단어를 추가 하여 요소 노드를 가져올 수 있음 이 경우 모든 태그 (노드) 정보를 가져오는게 아니라 내요에 해당하는 애들만 가져온다는 점이 다른 점이다.
  • children 프로퍼티는 해당 요소의 자식 노드 중 요소 노드만을 가리킵니다.
  • firstElementChild와 lastElementChild 프로퍼티는 각각 첫 번째 자식 요소 노드와 마지막 자식 요소 노드를 가리킵니다.
  • previousElementSibling과 nextElementSibling은 형제 요소 노드를 가리킵니다.
  • parentElement 는 부모 요소 노드를 가리킵니다.

  • 테이블 탐색하기
    <table> 요소는 기본 프로퍼티 이외에 다음과 같은 프로퍼티를 지원.
    table.rows는 <tr>요소를 담은 컬렉션을 참조.
    table.caption/tHead/tFoot은 각각 <caption>, <thead>, <tfoot> 요소를 참조.
    table.tBodies는 <tbody> 요소를 담은 컬렉션을 참조. 
    
    <thead>, <tfoot>, <tbody> 요소는 rows 프로퍼티를 지원.
    tbody.rows는 tbody 내 <tr> 요소 컬렉션을 참조.
    
    <tr> 요소는 다음 프로퍼티를 지원.
    tr.cells는 주어진 <tr> 안의 모든 <td>, <th>을 담은 컬렉션을 반환.
    tr.sectionRowIndex는 주어진 <tr>이 <thead>/<tbody>/<tfoot>안쪽에서 몇 번째 줄에 위치하는지를 나타내는 인덱스를 반환.
    tr.rowIndex는 <table>내에서 해당 <tr>이 몇 번째 줄인 지를 나타내는 숫자를 반환.
    
    <td>와 <th> 요소는 다음 프로퍼티를 지원.
    td.cellIndex는 <td>나 <th>가 속한 <tr>에서 해당 셀이 몇 번째인지를 나타내는 숫자를 반환.
    

    1. getElement, querySelector 로 요소 검색하기

    다른 접근 방법을 알아보자.

  • document.getElementById 혹은 id를 사용해 요소 검색하기 요소에 id 속성이 있으면 document.getElementById(id) 로 접근 할수 있다. 사용 예시 ```html
Element
  그냥 id 값을 그대로 사용하며 ㄴ접근할 수 있다.
  elem.style.background = 'red'만 써도 된단다.
  물론 선언된 변수가 없어야 한다.
  변수 선언시 선언된 변수값 사용

  - querySelectorAll 사용
  querySelectorAll(css) : css 선택자에 대응하는 모든 요소들을 찾아준다.
  ```javascript
  let elements = document.querySelectorAll('ul > li:last-child');
elem.querySelector(css)는 주어진 CSS 선택자에 대응하는 요소 중 첫 번째 요소를 반환
elem.querySelectorAll(css)[0]과 동일
  • matches elem.matches(css) : css 선택자와 일치하는지 여부를 판단해줌 일치 시 true, 불일치시 false

  • closest elem.closest(css)는 elem 자기 자신을 포함하여 CSS 선택자와 일치하는 가장 가까운 조상 요소를 찾을 수 있게 도와줌 태그를 반환해주는 것임

  • getElementsBy* getElementsByTagName(tag) : 주어진 태그에 해당하는 요소를 찾음 getElementsByClassName(className) : 주어진 class 속성값 기준으로 요소를 찾음 getElementsByName(name) : name 속성값으로 요소를 찾음

  • 살아있는 컬렉션 ‘getElementsBy’로 시작하는 모든 메서드는 살아있는 컬렉션을 반환함. 문서에 변경이 있을 때마다 자동갱신 됨 ‘querySelectorAll’은 정적인 컬렉션을 반환함.

5. 주요 노드 프로퍼티

  • DOM 노드 클래스 DOM 노드는 종류에 따라 프로퍼티가 다름

    계층 구조. ``` EventTarget Node text Element Comment

      HTMLElement
    
      HTMLBodyElement
    

    Node – 이 역시 ‘추상’ 클래스로 DOM 노드의 베이스 역할. 주요 트리 탐색 기능을 제공. Node 클래스의 객체는 절대 생성되지 않지만 이 클래스를 상속받는 클래스가 여럿 있습니다. 텍스트 노드를 위한 Text 클래스와 요소 노드를 위한 Element 클래스, 주석 노드를 위한 Comment클래스는 Node클래스를 상속받습니다. Element – DOM 요소를 위한 베이스 클래스입니다. HTMLElement – HTML 요소 노드의 베이스 역할을 하는 클래스입니다. 아래 나열한 실제 HTML 요소에 대응하는 클래스들은 HTMLElement를 상속받습니다. HTMLInputElement – 요소를 위한 클래스 HTMLBodyElement – <body> 요소를 위한 클래스 HTMLAnchorElement – 요소를 위한 클래스

    요소에 대응하는 DOM 객체. 이 객체는 HTMLInputElement 클래스를 기반으로 만들어짐. 해당 객체엔 아래에 나열한 클래스에서 상속받은 프로퍼티와 메서드가 있을 것임

    • HTMLInputElement – 입력 관련 프로퍼티를 제공하는 클래스
    • HTMLElement – HTML 요소 메서드와 getter, setter를 제공하는 클래스
    • Element – 요소 노드 메서드를 제공하는 클래스
    • Node – 공통 DOM 노드 프로퍼티를 제공하는 클래스
    • EventTarget – 이벤트 관련 기능을 제공하는 클래스
    • Object – hasOwnProperty같이 ‘일반 객체’ 메서드를 제공하는 클래스

객체는 constructor 프로퍼티를 가지기에 DOM 노드 클래스 이름을 확인할 수 있다. document.body.constructor.name toString 을 사용하거나 instanceof 를 사용해서도 가능함.

  - 'nodeType' 프로퍼티
    nodeType 프로퍼티는 DOM 노드의 '타입'을 알아낼 때 사용 (구식임)
    : 노드 타입 정보
    elem.nodeType == 1 – 요소 노드
    elem.nodeType == 3 – 텍스트 노드
    elem.nodeType == 9 – 문서 객체  

  - nodeName과 tagName으로 태그 이름 확인하기
    nodeName 이나 tagName 프로퍼티를 사용하면 DOM 노드의 태그 이름을 알아낼 수 있음.
    둘의 차이는?
     * tagName은 요소노드에만 존재함
     * nodeName은 모든 Node에 있음.
      요소노드를 대상으로 호출하면 tagName과 같은 역할을 한다.
      텍스트 노드, 주석노드 등에선 노드 타입을 나타내는 문자열을 반환한다.
  
  - innerHTML 로 내용 조작하기
    요소안의 HTML 을 문자열 형태로 받아올 수 있음.
    + 요소 안의 html을 수정하는 것도 가능함. => 페이지를 수정하는데 쓰이는 강력한 방법임!
  
  - 'innerHTML += ' 사용 시 주의점
    elem.innerHTML += 을 사용하여 html 소스를 추가할 수 있는데 
    유의해야할 점은 innerHTML+=의 동작방식이 어떻게 되냐면..
    1 기존 내용 삭제
    2 기존 내용과 새로운 내용을 합친 새로운 내용을 씀
    이렇게 되기 때문에 이미지나 리소스 전부 다시 불러와짐.
    이것 말고 html 추가하고 싶을 땐 다른 것을 쓰는게 좋다.

  - outerHTML 로 요소의 전체 HTML 보기
    outerHTML 프로퍼티엔 요소의 전체 HTML 이 담겨 있음.
    
    예시
  ```html
    <div id="elem">Hello <b>World</b></div>
    <script>
      alert(elem.outerHTML); // <div id="elem">Hello <b>World</b></div>
    </script>

    <div>Hello, world!</div>
    
    outerHTML 로 새롭게 교체한다면..
    <script>
      let div = document.querySelector('div');

      // div.outerHTML를 사용해 <p>...</p>로 교체
      div.outerHTML = '<p>새로운 요소</p>'; // (*)

      // 어! div는 그대로네요!
      alert(div.outerHTML); // <div>Hello, world!</div> (**)
    </script>
이렇게 했을 때 HTML의 출력은 바꾼 대로 문자열이 출력되는데
alert창에는 기존의 div를 출력함.

이런 결과가 나타나는 이유는 outerHTML에 할당 연산이 DOM 요소를 수정하지 않기 때문임. 
  • node Value/data 로 텍스트 노드 내용 조작하기 innerHTML에는 요소 노드에만 사용할 수 있음 nodeValue와 data를 사용하면 됨.

  • textContent로 텍스트만 조작하기 textContent를 사용하면 요소 내의 텍스트에 접근할 수 있음. <태그>는 제외하고 오로지 텍스트만 추출할 수 있음 * innerHTML과 비교 : innerHTML을 사용하면 사용자가 입력한 문자열이 ‘HTML 형태로’ 태그와 함께 저장. : textContent를 사용하면 사용자가 입력한 문자열이 ‘텍스트 형태로’ 저장되어 태그를 구성하는 특수문자들도 문자열로 처리.
  • ‘hidden’ 프로퍼티 요소를 보여줄지 말지 결정할 때 사용

  • 그 외의 프로퍼티 ```
    • value –
    • href – 의 ‘href’ 값이 저장.
    • id – ‘id’ 속성의 값이 저장. 대부분의 표준 HTML 속성은 그에 대응하는 DOM 프로퍼티를 가지고 있음 ``` 1. 속성과 프로퍼티 대부분의 HTML 속성은 DOM 객체의 프로퍼티가 된다.
  • DOM 프로퍼티 내장 프로퍼티만으로 충분하지 않은 경우가 있기 때문에 자신만의 프로퍼티를 만들 수도 있음. document.body에 새로운 프로퍼티 만들기 예시 ```javascript document.body.myData = { name: ‘Caesar’, title: ‘Imperator’ };

alert(document.body.myData.title); // Imperator

Element.prototype.sayHi = function() { alert(Hello, I'm ${this.tagName}); }; document.documentElement.sayHi(); // Hello, I’m HTML document.body.sayHi(); // Hello, I’m BODY


  이런식으로 프로토타입을 수정하여 모든 요소 노드에서 이 메서드를 사용할 수 있게 하였다.

  - html 속성
  html의 표준속성 id 같은 경우는 document.body.id 로 사용할 수 있으나
  document.body.something 이렇게 비표준 속성은 프로퍼티로 전환되지 않는다.

  input에선 type이 표준이 되지만 body에선 될 수 없다는 것도 유의해야한다.

  getAttribute 를 통해 비표준 속성에 접근할 수 있다.
  ```html
  <body something="non-standard">
  <script>
    alert(document.body.getAttribute('something')); // 비표준 속성에 접근
  </script>
  </body>

속성 추가도

  elem.setAttribute('Test', 123); // 속성 추가하기
  • 프로퍼티- 속성 동기화 id 속성의 경우는 프로퍼티로 수정했을 때 동기화 되어 수정된다. value의 경우 프로퍼티로 수정했을 때 속성이 수정되지는 않는다.

  • DOM 프로퍼티 값의 타입 input.checked 의 경우 불린형식임 style의 경우 속성은 문자열, 프로퍼티는 객체형 href의 경우 속성값이 #hello 라고 해도, 프로퍼티 값은 url로 반환된다.

  • 비표준 속성, dataset 비표준 속성의 사용예

    <!-- 이름(name) 정보를 보여주는 div라고 표시 -->
    <div show-info="name"></div>
    <!-- 나이(age) 정보를 보여주는 div라고 표시 -->
    <div show-info="age"></div>
    
    <script>
      // 표시한 요소를 찾고, 그 자리에 원하는 정보를 보여주는 코드
      let user = {
        name: "Pete",
        age: 25
      };
    
      for(let div of document.querySelectorAll('[show-info]')) {
        // 원하는 정보를 필드 값에 입력해 줌
        let field = div.getAttribute('show-info');
        div.innerHTML = user[field]; // Pete가 'name'에, 25가 'age'에 삽입됨
      }
    </script>
    

    위의 코드와 같이 비표준 속성값을 읽어와서 해당 객체의 정보를 원하는 곳에 출력시켜줄 수 있다.

혹은 style을 정의할 때 비표준 속성을 사용한다.

data- 라는 속성을 사용하면 개발자가 용도에 맞게 사용하도록 예약해두었다. dataset 에 접근하면 이 속성에 접근할 수 있다. 사용예는 다음과 같다.

    <body data-about="Elephants">
    <script>
      alert(document.body.dataset.about); // Elephants
    </script>

2. 문서 수정하기

생동감 있는 웹페이지의 관건은 dom 조작임

  • 요소 생성하기
      let div = document.createElement('div');
      let textNode = document.createTextNode('안녕하세요.');
    

    요소 노드, 텍스트 노드를 만들 수 있음

  • 메시지 생성하기 ``` 세단계로 메세지를 만들 수 있다. // 1. <div> 요소 만들기 let div = document.createElement(‘div’);

// 2. 만든 요소의 클래스를 ‘alert’로 설정 div.className = “alert”;

// 3. 내용 채워넣기 div.innerHTML = “안녕하세요! 중요 메시지를 확인하셨습니다.”;

  그러나 이렇게한다고 페이지에 나타나는 것은 아님

  - 삽입 메서드
  요소 삽입 메서드 append를 사용하면 위에서 생성한 요소를 삽입할 수 있다.
  ```javascript
  document.body.append(div);
  // body에 div에 해당하는 메세지를 출력해주는 것을 확인할 수 있다.

삽입 위치를 정할 수 있는데 이는 다음과 같다.

  • node.append(노드나 문자열) – 노드나 문자열을 node 끝에 삽입
  • node.prepend(노드나 문자열) – 노드나 문자열을 node 맨 앞에 삽입
  • node.before(노드나 문자열) – 노드나 문자열을 node 이전에 삽입
  • node.after(노드나 문자열) – 노드나 문자열을 node 다음에 삽입
  • node.replaceWith(노드나 문자열) – node를 새로운 노드나 문자열로 대체

  • insertAdjacentHTML/Text/Element
  • ‘beforebegin’ – elem 바로 앞에 html을 삽입.
  • ‘afterbegin’ – elem의 첫 번째 자식 요소 바로 앞에 html을 삽입.
  • ‘beforeend’ – elem의 마지막 자식 요소 바로 다음에 html을 삽입.
  • ‘afterend’ – elem 바로 다음에 html을 삽입.

elem.insertAdjacentHTML(where, html)은 두 가지 형제 메서드가 있습니다. elem.insertAdjacentText(where, text) – insertAdjacentHTML과 문법은 같은데, HTML 대신 text를 ‘문자 그대로’ 삽입한다는 점이 다름. elem.insertAdjacentElement(where, elem) – 역시 같은 문법인데, 요소를 삽입한다는 점이 다름.

  • 노드 삭제하기
      node.remove()
      setTimeout(() => div.remove(), 1000);
    

    를 사용하면 사용한 노들르 지울 수 있다.

  • cloneNode로 노드 복제하기 기존 메세지창과 유사한 메세지창을 띄워달라는 요구사항이 있는 경우
  let div2 = div.cloneNode(true); // 메시지 창 복제
  div2.querySelector('strong').innerHTML = '안녕히 가세요!'; // 복제한 메시지 창 내용 수정

  div.after(div2); // 복제한 메시지 창을 기존 메시지 창 다음에 보여줌

위와 같이 코딩하여 기존의div를 복사하여 사용할 수 있다.

  • DocumentFragment 특별한 DOM 노드 타입임. 여러 노드로 구성된 그룹을 감싸 다른 곳으로 전달하게 해주는 래퍼처럼 동작 예시) ```html
      사실 잘 쓰지는 않는다. 그냥 append 안에 전개문법...을 사용하여 반환할 수 있기 때문임.
    
      - 구식 삽입, 삭제 메서드
      * parentElem.appendChild(node)
      parentElem의 마지막 자식으로 node를 추가함
    
      * parentElem.insertBefore(node, nextSibling)
      node를 parentElem안의 nextSibling앞에 추가함
    
      * parentElem.replaceChild(node, oldChild)
      parentElem의 자식 노드 중 oldChild를 node로 교체함
      
      * parentElem.removeChild(node)
      node가 parentElem의 자식 노드라는 가정하에 parentElem에서 node를 삭제함
    
      - 'document.write’에 대한 첨언
      ```html
      <p>페이지 어딘가...</p>
      <script>
        document.write('<b>자바스크립트를 사용해 Hello 입력</b>');
      </script>
      <p>끝</p>
    

    이런식으로 쓰면 그자리에 즉시 해당 문자열로 출력한다.

    그런데 document.write는 페이지를 불러오는 도중에만 작동하기 때문에 기존에 있었던 문자열을 다 초기화 시키고 새로 불러오는 동작을 수행한다 보면 된다. 그래서 잘 안쓴단다.