호이스팅(Hoisting)
자바스크립트에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 말한다. var로 선언한 변수의 경우, 호이스팅 시 undefined로 변수를 초기화한다. 반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않는다. 호이스팅을 설명할 땐 주로 "변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는 것"으로 말하곤 한다. 따라서 변수를 정의하는 코드 보다 사용하는 코드가 앞서 등장할 수 있다. 다만 선언과 초기화를 함께 수행하는 경우, 선언 코드까지 실행해야 변수가 초기화된 상태가 됨을 주의해야 한다.
자바스크립트는 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당한다. 덕분에 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있다. 그 예시는 아래와 같다.
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
catName("호랑이");
/*
결과: "제 고양이의 이름은 호랑이입니다"
*/
위 코드가 일반적인 작성 순서라면, 이번에는 함수를 선언하기 전에 먼저 호출해보자.
catName("호랑이");
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
/*
결과: "제 고양이의 이름은 호랑이입니다"
*/
위 코드는 함수 호출이 함수 자체보다 앞서 존재하지만 잘 동작한다.
이벤트 버블링
한 요소에 이벤트가 발생하면 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작한다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작한다.
<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
위 코드에서 가장 안쪽에 있는 <p>를 클릭하면 아래와 같은 순서로 이벤트가 일어난다.
- <p>에 할당된 onclick 핸들러가 동작
- 바깥의 <div>에 할당된 핸들러가 동작
- 그 바깥의 <form>에 할당된 핸들러가 동작
- document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작
스코프(scope)
자바스크립트에서 스코프(scope)란, 변수에 접근할 수 있는 범위를 말한다. 자바스크립트에서 스코프는 2가지 타입이 있다.
- global (전역): 전역에 선언되어있어 어느 곳에서든지 해당 변수에 접근할 수 있음
- local (지역): 해당 지역에서만 접근할 수 있음
함수는 자바스크립트에서 클로저 역할을 하기 때문에 스코프를 생성하므로 함수 내에 정의된 변수는 외부 함수나 다른 함수 내에서는 접근할 수 없다. 아래 예시를 보자.
function exampleFunction() {
var x = "declared inside function";
// x는 오직 exampleFunction 내부에서만 사용 가능.
console.log("Inside function");
console.log(x);
}
console.log(x); // 에러 발생
반면, 변수를 함수 외부(전역)에서 선언하면 코드가 유효하다.
var x = "declared outside function";
exampleFunction();
function exampleFunction() {
console.log("Inside function");
console.log(x);
}
console.log("Outside function");
console.log(x);
프로토타입(prototype)
자바스크립트는 흔히 프로토타입 기반 언어(prototype-based language)라 불린다. 이는 모든 객체들이 메소드와 속성들을 상속 받기 위한 테플릿으로써 프로토타입 객체(prototype object)를 가진다는 의미다. 프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메소드와 속성을 상속 받을 수도 있고 그 상위 프로토 타입 객체도 마찬가지다. 이를 프로토타입 체인(prototype chain)이라 부르며 다른 객체에 정의된 메소드와 속성을 한 객체에서 사용할 수 있도록 한다.
정확히는 상속되는 속성과 메소드들은 각 객체가 아니라 객체의 생성자의 prototype이라는 속성에 정의되어 있다. 자바스크립트에서는 객체 인스턴스와 프로토타입 간에 연결이 구성되며 이 연결을 따라 프로토타입 체인을 타고 올라가며 속성과 메소드를 탐색한다.
function Person(first, last) {
// 속성과 메소드 정의
this.first = first;
this.last = last;
//...
}
// 인스턴스 생성
var person1 = new Person('Bob', 'Smith');
코드가 위와 같을 때 자바스크립트 콘솔에서 "person.1"을 치게 되면, 브라우저는 아래처럼 해당 객체의 멤버 이름을 자동 완성 팝업으로 보여주게 된다.
위에서 person1의 프로토타입 객체인 Person()에 정의된 멤버들(last와 first)을 볼 수 있다. 또한 valueOf처럼 Person()의 프로토타입 객체인 Object에 정의된 다른 멤버도 볼 수 있다. 이는 프로토타입 체인이 동작한다는 뜻이다.
Object에 정의되어 있는 메소드(valueOf)를 person1에서 호출해보자.
person1.valueOf()
아래처럼 객체의 값을 반환한다.
shadow DOM
shadow DOM이란 DOM의 구조를 갖고 있으나, 외부에 노출되지 않은 DOM을 말하며, DOM의 구조를 캡슐화할 때 사용한다.
- shadow host: 기준이 되는 element
- shadow root: shadow DOM tree의 root node
- normal (= regular, light) DOM: (shadow DOM과 구분을 하기 위해) 기존에 우리가 알고 있던 일반적인 DOM
shadow DOM의 특징
- 외부의 style은 적용되지 않음
- shadow DOM을 추가하거나 접근하기 위해서는 별도의 방법이 필요함
- 데코레이터에서 만들어진 shadow DOM은 스크립트로 접근하거나 수정이 불가
- custom element로 만들어진 shadow DOM은 스크립트로 수정 가능
- 일반적인 DOM은 트리가 렌더링 된 후 DOM 트리가 수정되서 비용이 크지만, shadow DOM은 shadow Host를 만나는 순간 렌더링 되기 때문에 비용을 줄일 수 있음
HTML에서 <input type="range" />를 작성하면 range 바가 뜬다. 이 때 자동으로 컨트롤이 만들어지는데, shadow DOM이 사용되었기 때문이다. shadow DOM을 보려면 크롬 개발자 모드에 진입(F12)하여, 설정(Settings) - Preferences 에서 Elements 메뉴 아래에 있는 "Show user agent shadow DOM"을 체크하면 된다.
strict mode (엄격 모드)
sloppy mode(느슨한 모드)에 반대되는 개념으로, 자바스크립트 문법을 엄격히 확인하기 위해 사용된다. 스크립트의 시작 부분(전체 스크립트에 적용), 또는 함수의 시작 부분(부분 함수에 적용)에 "use strict"; 를 쓰면 발동된다.
"use strict"; // 스크립트 전체에 strict mode 적용
var s = "This is how to declare strict mode.";
function strict(){
'use strict'; // 부분 함수에 strict mode 적용
return "This is STRICT MODE";
}
참고로, 자바스크립트 모듈에는 기본적으로 strict mode가 적용된다.
function testModule() {
// 모듈에는 strict mode가 기본 적용됨
}
export default testModule;
strict mode는 다음과 같은 변화를 일으킨다.
- 기존에 무시되던 에러들을 보여줌
- 자바스크립트 엔진의 최적화 작업을 어렵게 하는 실수들을 바로 잡음(가끔 sloppy mode 모다 더 빨리 작동함)
- ECMAScript의 차기 버전들에서 정의될 문법을 금지함
'웹_프론트엔드 > 로드맵 챌린지' 카테고리의 다른 글
VCS - Git 기본 사용법 (0) | 2022.01.08 |
---|---|
VCS - 버전 관리(Version Control Systems)를 쓰는 이유 (0) | 2022.01.07 |
JavaScript - 모듈러 자바스크립트와 ES6+ (0) | 2022.01.05 |
JavaScript - Fetch API / Ajax (XHR) (0) | 2022.01.03 |
JavaScript - DOM 조작 방법 (0) | 2021.12.31 |