프론트엔드 날개달기 : Vuejs, React 배우기 전에 꼭 알아야하는 지식

섹션 0

  • DOM 이란 ?
  • BOM 이란 ?
  • script 태그 defer, async
  • this란 무엇인가 ?

JS : html 문서를 제어하기 위해 만들어진 언어

렌더링 엔진

브라우저 내의 엔진으로, html 문서를 한 줄씩 해석하여 객체화함으로서 js가 접근할 수 있도록 함

javascript의 모든 객체는 속성과 메서드를 가지며, 속성은 값을 불러오는 역할, 메서드는 해당 값에 접근하는 역할을 한다. 이 때, 메서드는 값을 얻어오는 get- 과 값을 변경하는 set- 으로 나뉜다.

DOM 이란 ?

DOM (Document Object Model) : 문서 객체 모델

브라우저에서 js로 html을 제어하도록 제공하는 API(브라우저에서 제공하는 기능)

* CSS Object Model : css를 제어하도록 한 것

트리구조

html 문서는 웹의 렌더링 엔진에 의해 해석되어 DOM 트리로 변환된다. 트리는 하나의 부모태그와 n개의 자식태그를 가지는 구조로, 이 경우 각각의 태그는 노드로 구조화할 수 있으며, 이 때 js는 각각의 노드에 접근하여 제어한다.

* document 객체 : dom 트리의 최상위 객체로 문서 자체, 즉 진입점을 나타낸다.

document.getRootNode() -> #document 
// chileNodes 를 사용하여 자식노드 접근 가능

BOM 이란 ?

BOM (Browser Object Model) : 브라우저 객체 모델

웹 브라우저를 객체화 한 것으로, 이 때 객체화는 브라우저를 스크립트언어로 제어하기 위한 작업이다.

Browser 객체

Object Discription
window 모든 객체가 소속된 객체이며, 브라우저 창을 의미
document 현재 문서(DOM)에 대한 정보를 갖고 있는 객체
history 현재의 브라우저가 접근했던 URL history를 제어
location 문서의 주소와 관련된 객체로, window 객체의 프로퍼티인 동시에 document의 프로퍼티. 이를 이용하여 윈도우의 문서 URL 변경 또는 문서의 위치에 대한 정보 취득 가능

* property : 객체를 구성하는 블록
screen 사용자의 디스플레이 화면에 대한 정보를 지님
navigator 실행 중인 애플리케이션에 대한 정보를 알 수 있으며, 크로스 브라우징 이슈를 해결할때 사용할 수 있다.
사용 예시
// window 객체
// window. 은 생략 가능

window.open('URL') // URL 의 페이지가 열림
window.close() // 해당 창이 닫힘

// document 객체
// window에 포함된 객체로 window.document로 사용 가능하다 window. 생략

document.querySelector('#id') // 앵커 선택
document.querySelector('#id').textContent = 'hello' // content 변경

// history 객체

history.back() // 뒤로가기
history.forward() // 앞으로 가기

// location 객체

location.host // 현재 페이지의 호스트 반환
loscation.href = 'URL' // 주소를 URL로 변경
location.reload() //  현재 페이지의 리소스를 다시 불러옴

// screen 객체

console.dir(screen) // 현재 디스플레이의 사이즈를 포함한 다양한 정보

// navigator 객체

navigator.geolocation.getCurrentPosition() // 현재 앱에 대한 위치 정보
navigator.appName // 앱(브라우저) 이름
navigator.appVersion // 앱(브라우저) 버전 정보
navigator.userAgent // 서버에 요청할 때 앱에 대한 정보

script 태그 defer, async

<script src=""></script>
<button id = "btn">button</button>
let btn = document.querySelector('#btn')

btn.addEventListener('click', function () {
    alert('Hello World!')
;})

위 코드에서 error 가 발생하는 이유

브라우저에서는 html 파일을 만났을 때 순차적으로 코드를 읽기에, script 태그를 만나면 script 를 실행한다. 이 때, #btn이 파싱되기 전에 script 를 삽입하면, document.querySelector(‘#btn’) 의 값은 null이 되기에 error가 발생하는 것이다.

해결 방법

body 태그의 최 하단에서 script 로드

html의 파싱이 완료된 후 script 실행

<button id = "btn">button</button>
<script src=""></script>
load 이벤트 리스너 등록
  1. window.onload : html 파싱 및 DOM 생성, 외부 컨텐츠 로드 완료 후 발생하는 이벤트

    window.onload = function(){
     let btn = document.querySelector('#btn');
     btn.addEventListener('click', function(){
         alert('Hello World!');
     });
    };
    

    * onload 이벤트는 외부 컨텐츠가 많을 경우 비효율적

  2. DOMContentLoaded : html 파싱 및 DOM 생성 후 발생하는 이벤트

    document.addEventListener('DOMContentLoaded', function(){
     let btn = document.querySelector('#btn');
     btn.addEventListener('click', function(){
         alert('Hello World!');
     });
    });
    

    * onload보다 더 빠르게 실행됨 : 두 방법을 모두 작성 후 실행하여 확인했을 시, DOMContentLoaded로 작성된 코드가 실행되어 나타나는 것을 볼 수 있음

html 파싱과 동시에 script 태그를 받아올 수는 없을까 ?

DOMContentLoaded 의 경우, html parsing -> Script fetch -> script execution 의 단계로 작업이 수행된다. 이 때, html parsing 단계에서 script fetch를 진행하기 위해, html5에서 defer와 async 가 등장하였다.

  1. defer

    defer 속성은 HTML 파싱과 함께 비동기로 javascript 파일을 불러오며, HTML 파싱 후, 불러온 코드를 실행한다. 따라서, 선택자가 가리키는 요소가 파싱되지 않았더라도, 오류가 발생하지 않는다

    <script src="" defer></script>
    
  2. async

    defer과 같이 HTML 파싱 과정에서 비동기로 javascript 파일을 불러오나, 파싱이 완료되지 않았더라도, 먼저 로딩되는 javascript 파일이 실행된다. 따라서, 선택자가 가리키는 요소가 파싱되지 않은 경우 오류가 발생한다

    <script src="" async></script>
    

this란 무엇인가 ?

this는 호출한 객체를 가리키며, 호출한 객체가 존재하지 않을 경우 기본적으로 window 객체를 가리킨다.

예시 1

let person = {
    name: 'psw',
    age: 22,
    printThis: function(){
        console.log(this === person); 
    },
};

let printThis = person.printThis;
person.printThis(); // true
printThis(); // False, this === window

예시 2 : html에서 javascript를 호출했을 경우

<script src="" defer></script>
<button>button</button>
let btn = document.querySelector('#btn');

btn.addEventListener('click', function () {
    console.log(this); // <button>button</button>
    console.log(this === btn); // true
});

예시 3 : this 를 설정하고 싶을 때

function printThis(){
    console.log(this);
}

let person1 = {
    name: 'psw',
};

let printThis1 = printThis.bind(person1);
printThis1(); // {name: 'psw'}

그러나, 아래의 코드를 실행한 결과 또한 위와 동일하게 {name: ‘psw’} 가 되는 것을 볼 수 있는데, 그 이유는 bind는 한 객체에 한 번만 등록할 수 있기 때문이다.

let person2 = {
    name: 'bsw',
};

let printThis2 = printThis1.bind(person2);
printThis2(); // {name: 'psw'}

예시 4

let person = {
    name = 'psw',
    hello: function(){
        setTimeout(function(){
            console.log(this); // Window { ... }
            console.log(this.name); // undefined
        }, 1000);
    },
};

print.hello();

위 코드의 경우, this.name을 출력하려면 아래와 같이 this를 바인딩 해주어야 한다

let person = {
    name = 'psw',
    hello: function(){
        setTimeout(function(){
            console.log(this); // {name: 'psw'}
            console.log(this.name); // psw
        }.bind(this), 1000); // setTimeout의 this는 person
    },
};

print.hello();

예외

화살표 함수 (Arrow Function)

화살표 함수는 자신을 포함하는 외부 스코프에서 this를 계승받는 성질을 지닌다

let person = {
    name = 'psw',
    hello: function(){
        setTimeout(() => {
            console.log(this); // {name: 'psw'}
            console.log(this.name); // psw
        }, 1000);
    },
};

print.hello();

예시 4의 첫 코드와 동일한 코드에서 콜백 함수를 화살표 함수로 변경한 결과, 외부 스코프를 계승받아 Window가 아닌, person이 this가 되는 것을 볼 수 있다

화살표 함수를 사용하면 안 되는 경우

객체 메서드를 선언할 때

let person = {
    name = 'psw',
    printThis: () => {
        console.log(this); // window 객체 (person이 지닌 전역 스코프를 계승받음)
    }
};

addEventLister 함수의 콜백함수

let btn = document.querySelector('#btn');

btn.addEventListener('click', () => {
    console.log(this); // window 객체
    console.log(this === btn); // false
});
Strict Mode

strict mode 에서는 호출한 객체가 없을경우, 기본값이 window 가 아닌 undefined가 된다

// non strict mode

function printThis(){
    console.log(this);
}
printThis(); // Window

// strict mode

'use strict';
function printThis(){
    console.log(this);
}
printThis(); // undefined

태그:

카테고리:

업데이트: