[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
-
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
- 일반 객체의 데이터 개수를 알려면
- 객체는 속성 접근자(property accessor) 문법을 통해서,
-
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 처럼 요소 끝에 자식을 넣는다. - 이미 문서에 존재하는 객체를 인수에 넣어서 호출하면 그 요소객체를 복사하지 않고 위치만 이동시킨다.
- beforeWhat에
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을 찾으려고 하면 당연히 없기 때문에 에러를 뿜는다.
- 다음 형제가 없을 때 console에서 에러를 뿜는 이유는?
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()
- 이벤트가 일으키는 브라우저의 기본 동작과정을 취소하기
이벤트 전파
- 이벤트는 흘러 다닌다. (바깥에서부터 들어와서 타겟을 거쳐서 밖으로 다시 빠져 나간다.)
- 바깥쪽 요소에서부터 이벤트 리스너를 찾으면서 들어올 때 캡처링
- 이벤트 발생 요소에서부터 바깥으로 이벤트 리스너를 찾으면서 나갈 때 버블링
- 그냥 이벤트 리스너를 설정하면 캡처링 과정을 지나서 버블링 과정에서 이벤트가 발생한다.
댓글남기기