형식의 유효성을 일관성있게 유지하기 위해 내장함수 encodeURIComponent를 사용하여 이스케이프 처리를 해야 한다.
let name = "name";
let value = "John Smith";
//인코딩 처리 -> my%20name=John%20Smith
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);
쿠키의 한계 1. encodeURIComponent로 인코딩한 후의 name=value 쌍이 4KB를 넘으면 쿠키에 저장할 수 없다. 2. 도메인 하나당 저장할 수 있는 쿠키의 수는 20여개로 한정되어 있다. 개수는 브라우저에 따라 차이가 있다.
쿠키의 옵션
쿠키에는 여러 옵션들이 존재한다.
개발자도구(F12) Application >> Cookies에서 쿠키를 확인할 수 있다.
1. Name & Value
데이터를 저장하고 읽는 데 사용하는 옵션으로 반드시 지정해주어야 한다.
document.cookie = "user=John"
2. Path
옵션을 입력하지 않으면 현재 도메인의 경로로 자동 입력된다.
특별한 경우가 아니라면 path=/와 같이 루트로 설정해 웹사이트의 모든 페이지에서 쿠키에 접근할 수 있도록 해야한다.
예를들어, path=/admin으로 설정한 쿠키는 /admin과 그 하위 경로에는 접근 가능하지만 /home과 같은 다른 경로에서는 사용할 수 없다.
document.cookie = "user=John; path=/"
3. Domain
쿠키에 접근 가능한 domain을 지정한다.
옵션을 입력하지 않으면 현재 domain의 경로로 자동 입력된다.
domain에 루트도메인을 명시적으로 설정하여 서브 도메인에서도 메인 도메인에서 생성한 쿠키 정보를 사용할 수 있다.
document.cookie = "user=John; domain=site.com"
4. Expires / Max-age
expires(유효 일자), max-age(만료 일자) 옵션을 지정하여, 쿠키의 만료 기간을 설정할 수 있다.
expires는 GMT 혹은 UTC포맷으로 설정해야한다.
세션 쿠키(Session Cookie) expires, max-age 옵션이 지정되어있지 않아, 브라우저가 닫힐 때 삭제되는 쿠키.
max-age는 expires의 대안으로, 쿠키 만료기간을 설정할 수 있게 해준다.
현재부터 설정하고자 하는 만료일시까지의 시간을 초로 환산한 값을 설정한다.
//expires
//toUTCString() 메서드를 사용하여 UTC포맷으로 쉽게 변환이 가능하다.
let date = new Date(Date.now() + 86400e3);
date = date.toUTCString();
document.cookie = "user=John; expires=" + date;
//max-age
document.cookie = "user=John; max-age=3600";
5. Secure
해당 옵션을 설정 시, HTTPS로 통신하는 경우에만 쿠키가 전송된다.
// 설정한 쿠키는 HTTPS 통신시에만 접근할 수 있음
document.cookie = "user=John; secure";
6. HttpOnly
HttpOnly 옵션이 설정된 쿠키는 document.cookie로 쿠키 정보를 읽을 수 없다.
document.cookie = "user=John; httpOnly"
7. Samesite
XSRF 공격을 막기 위해 만들어진 옵션이다.
samesite 옵션을 XSRF 토큰 같은 다른 보안기법과 함께 사용하면 보안을 강화할 수 있다.
2017년 이전 버전의 브라우저에서는 samesite를 지원하지 않는다.
samesite(=strict) 사이트 외부에서 요청을 보낼 때, 해당 옵션이 있는 쿠키는 절대로 전송되지 않는다.
samesite=lax GET방식의 작업 혹은 최상위 레벨 탐색(브라우저 주소창에서 URL변경 등)에서의 작업이 이루어질 때만 쿠키가 서버로 전송된다.
document.cookie = "user=John; samesite"
쿠키 함수
getCookie(name)
정규 표현식을 사용하여 가장 빠르게 접근할 수 있다.
// 주어진 이름의 쿠키를 반환하는데,
// 조건에 맞는 쿠키가 없다면 undefined를 반환합니다.
function getCookie(name) {
let matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : undefined;
}
setCookie(name, value, options)
function setCookie(name, value, options = {}) {
options = {
path: '/',
// 필요한 경우, 옵션 기본값을 설정할 수도 있습니다.
...options
};
if (options.expires instanceof Date) {
options.expires = options.expires.toUTCString();
}
let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);
for (let optionKey in options) {
updatedCookie += "; " + optionKey;
let optionValue = options[optionKey];
if (optionValue !== true) {
updatedCookie += "=" + optionValue;
}
}
document.cookie = updatedCookie;
}
// Example of use:
setCookie('user', 'John', {secure: true, 'max-age': 3600});
deleteCookie(name)
//만료 기간을 음수로 설정하여 쿠키를 삭제
function deleteCookie(name) {
setCookie(name, "", {
'max-age': -1
})
}
//then의 두 번째 파라미터로 error를 받아서 처리.
promise().then(message, error);
//catch를 이용한 처리를 더 권장한다.
promise().then((message) => {
console.log(message)
}).catch((message) => {
console.log(message)
})
프로미스의 연결 ( Promise Chaining )
여러개의 프로미스를 연결하여 사용 가능하다.
then()메서드를 호출하여 새로운 프로미스 객체가 반환되고, 이에 따른 후속처리를 계속 진행할 수 있다.
const url = 'https://jsonplaceholder.typicode.com/posts';
// 포스트 id가 1인 포스트를 검색하고 프로미스를 반환한다.
promiseAjax('GET', `${url}/1`)
// 포스트 id가 1인 포스트를 작성한 사용자의 아이디로 작성된 모든 포스트를 검색하고 프로미스를 반환한다.
.then(res => promiseAjax('GET', `${url}?userId=${JSON.parse(res).userId}`))
.then(JSON.parse)
.then(render)
.catch(console.error);
함수를 콜백함수로 사용할 경우, 함수의 이름만 넘겨주면 된다.(함수를 인자로 사용할 때 ()를 붙일 필요가 없다.)
function whosYourDaddy(name, callback){
console.log("우리 아부지 성함은 " + name +"입니다");
callback();
}
function test(){
console.log("니 내 아나?");
}
whosYourDaddy('김철수', test);
콜백 함수 주의사항 - this를 사용 시
콜백함수에서의 this는 기본적으로 값에 의한 호출(call by value)을 하기 때문에, window객체를 가리킨다.
자바스크립트를 이용하여 비동기적으로 서버와 브라우저가 데이터를 교환할 수 있는 통신방식이다.
서버와 통신하기 위해 XMLHttpRequest 객체를 사용한다.
JSON, XML, HTML, 일반 텍스트 형식 등을 포함한 다양한 포맷을 주고 받을 수 있다.
비동기 전송방식(비동기식 처리모델) 병렬적인 테스크를 수행한다. 화면이 종료되지 않더라도 대기하지 않고 다음 작업을 수행한다. (이벤트핸들러, Timer, Ajax)
사용자의 이벤트가 있으면 전체 페이지의 새로고침이 아닌 일부분만 갱신할 수 있게 해준다.
XMLHttpRequest ( XHR )
서버와 상호작용할 때 사용하며, XHR을 사용하면 페이지의 새로고침 없이도 URL에서 데이터를 가져올 수 있다.
XML 뿐만 아니라 모든 종류의 데이터를 가져올 수 있다.
const xhr = new XMLHttpRequest(); //객체 생성
xhr.open('GET', 'js/test.json'); //비동기 방식 open
xhr.setRequestHeader('Content-type', 'application/json') //MIME-type 지정
xhr.send(); //전송
xhr.onload = function(){
if(xhr.status===200){ //status = response 상태 코드 반환 : 200 정상응답
console.log(xhr.responseText);
}
}
XMLHttpRequest.open(method, URL(, async)
method : HTTP method (GET, POST 등)
URL : 주소 또는 파일명
async : default는 true이며 비동기 방식, false는 동기 방식
XMLHttpRequest.send
요청을 전송한다. 비동기 요청인 경우 send는 요청을 전송하는 즉시 반환한다.
GET의 경우, URL의 일부분인 쿼리스트링으로 데이터를 서버로 전송하며 send메서드 안의 파라미터값은 무시된다.
let sum = (a, b) => a + b;
alert( sum(1, 2) ); // 3
//위의 화살표 함수와 동일한 표현이다.
let sum = function(a, b) {
return a + b;
};
(a,b) => a+b는 실행되는 순간 a+b를 평가하고 그 결과를 반환한다.
인수가 한 개만 존재한다면 괄호를 생략할 수 있다.
let mul = a => a * 2;
인수가 존재하지 않을 때는 괄호가 있어야하며, 괄호를 비워놓으면 된다.
let void = () => console.log("텅텅 빔");
화살표 함수를 사용하면 아래와 같이 동적인 함수 생성이 가능하다.
let age = prompt("19세 미만 출입금지.", 18);
let welcome = (age > 19) ?
() => alert('출입') :
() => alert("불가");
화살표 함수의 제한점
1. this나 super에 대한 바인딩이 없다.
//화살표 함수의 this는 상위의 this를 그대로 가져온다.
let board = {
title: "1",
content: ["a", "b", "c"],
showList() {
this.content.forEach( // this === board
content => alert(this.title + ': ' + content) // this === board
);
}
};
board.showList();
// 1 : a
// 1 : b
// 1 : c
2. 메서드나 생성자로 사용할 수 없다.
//메소드를 호출한 객체를 가리키지 않고 상위 컨택스트인
//전역 객체 Window를 가리키게 된다. -> undefined
const dog = {
name: 'guzzi',
howl: () => console.log(`mung ${this.name}`)
};
dog.howl(); // mung undefined
//프로토타입 메서드 역시 마찬가지다.
const dog = {
name: 'guzzi',
};
Object.prototype.howl = () => console.log(`mung ${this.name}`);
dog.howl(); // mung undefined
//생성자 함수는 프로토타입 프로퍼티를 가지며
//프로토타입 프로퍼티가 가리키는 프로토타입 객체의 생성자를 사용한다.
//화살표함수는 프로토타입 프로퍼티를 가지고 있지 않다.
const dog = (name) => {
this.name = name
};
// 화살표 함수는 프로토타입 프로퍼티가 없다
console.log(dog.hasOwnProperty('prototype')); // false
const cat = new dog("guzzi"); // TypeError: dog is not a constructor
3. 일반적으로 범위를 지정할 때 사용하는 call, apply, bind메서드를 사용할 수 없다.
단어 - /filter/g 전체에서 f 따로 i 따로 찾는게 아니라 'filter' 라는 단어에 매칭되는것을 찾음
단어 제외 - /\b(?:(?!to)\w)+\b/g 전체에서 'to' 라는 단어를 빼고 다른 단어 매칭 / 확인결과 "Tutorial" 도 제외됨.
단어 제외 - \b(?!\bto\b)\w+\b 전체에서 'to' 라는 단어를 빼고 다른 단어 매칭 / 확인결과 "Tutorial" 는 제외 안됨. 이게 더 정확하다고 볼수있을듯.
이메일 - /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i '시작을' 0~9 사이 숫자 or a-z A-Z 알바펫 아무거나로 시작하고 / 중간에 - _ . 같은 문자가 있을수도 있고 없을수도 있으며 / 그 후에 0~9 사이 숫자 or a-z A-Z 알바펫중 하나의 문자가 없거나 연달아 나올수 있으며 / @ 가 반드시 존재하고 / 0-9a-zA-Z 여기서 하나가 있고 / 중간에 - _ . 같은 문자가 있을수도 있고 없을수도 있으며 / 그 후에 0~9 사이 숫자 or a-z A-Z 알바펫중 하나의 문자가 없거나 연달아 나올수 있으며 / 반드시 . 이 존재하고 / [a-zA-Z] 의 문자가 2개나 3개가 존재 / 이 모든것은 대소문자 구분안함
핸드폰 번호 - /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/ 시작을 숫자 01로 시작하며 그 후에 0,1,6,7,8,9 중에 하나가 나올수도 있으며 / 하이픈 - 하나 존재할수도 있으며 / 숫자 3~4개 이어지고 / 또 하이픈 - 하나 존재할수도 있으며 / 숫자 4개가 이어짐
자바스크립트에서는 모든 것이 객체이기 때문에 배열의 각 요소를 다시 배열로 정의해 중첩하는 식으로 다차원 배열을 구현하게 된다. 중첩 배열 형태인 것이다.
그렇기 때문에 다차원이 되면 배열 탐색 속도가 느려지고 언어적인 특성상 배열 요소 자체가 객체이다.
따라서 대량의 데이터 처리에 불리하기에 권장하지 않는다.
배열 생성
1. var arr = [배열요소1, 배열요소2,...]; // 배열 리터럴을 이용하는 방법
2. var arr = Array(배열요소1, 배열요소2,...); // Array 객체의 생성자를 이용하는 방법
3. var arr = new Array(배열요소1, 배열요소2,...); // new 연산자를 이용한 Array 객체 생성 방법
배열 순회
// 기본 for문
let data = [1, 2, 3 ];
for(let i = 0; i < data.length; i++){
console.log(i);
}
// for Each
let data = [1, 2, 3 ];
data.forEach(function(value){
console.log("valueis", value);
});
// For of
let data = [1, 2, 3 ];
for( let value of data ){
console.log( value);
}
// for in : 상위 객체의 함수가 출력될수 있기 때문에 조심해서 사용하도록 한다.
let data = [1, 2, 3 ];
for( let idx in data ){
console.log( data[idx]);
}
메서드
메서드
설명
push()
배열의 가장 맨 뒤에 요소 추가
pop()
배열의 가장 맨 뒤 요소 삭제
reverse()
배열의 순서를 반대로
sort()
오름차순 정렬 (문자열 기준)
splice(start, del, item1......)
기존 요소 제거 및 요소 추가 start INDEX부터 del만큼 제거, item이 있다면 item1, item2......추가
join() toString()
모든요소를 하나의 문자열로 반환 join은 구분자 사용가능하며 기본값은 ','
slice(start, end)
start INDEX부터 end-1 INDEX까지의 배열 반환
concat()
배열 뒤에 새로운 배열을 합침
map()
기존의 배열을 콜백함수에 의해 새로운 배열을 만들 때 사용
filter()
해당 배열의 모든 요소에 대하여 반복적으로 콜백함수를 실행 콜백함수의 조건의 대한 결과 값이 true인 요소들만을 새로운 배열에 담아 반환한다.
every()
배열 내 모든 요소들에 대한 조건이 모두 만족할 때 true를 반환
some()
배열 내 모든 요소들에 대한 조건이 하나라도 만족할 때 true를 반환
reduce() reduceRight()
배열의 모든 요소를 하나의 값으로 줄이기 위해 두 개의 인수를 전달받는 콜백함수 실행 reduce는 배열의 0번INDEX에서 마지막INDEX, reduceRight는 반대
HTML에 접근하기 위한 모델(인터페이스)이며, HTML을 컨트롤하기 위한 방법 그 자체를 기술한 것이다. 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공한다. 우리는 이 DOM으로 모든 HTML요소 및 속성, CSS스타일을 변경할 수 있으며, 이벤트를 추가하고, 이벤트에 반응할 수 있다.
DOM은 W3C의 표준 객체 모델이다.
DOM에 접근해 보자
문서가 로드될 때(모든 DOM을 사용할 수 있게 되는 때) 실행되는 함수를 정의하였다. 새로운 H1 element를 생성하고, element에 text를 추가하며, H1을 이 문서의 트리에 추가한다.
<html>
<head>
<script>
// run this function when the document is loaded
window.onload = function() {
// create a couple of elements in an otherwise empty HTML page
var heading = document.createElement("h1");
var heading_text = document.createTextNode("Big Head!");
heading.appendChild(heading_text);
document.body.appendChild(heading);
}
</script>
</head>
<body>
</body>
</html>
브라우저는 HTML문서를 로드한 후 해당 문서에 대한 모델을 메모리에 생성한다. 이 때 생성된 객체들의 구조를 DOMTREE라 부른다.
DOM-TREE 구조
DOM Tree와 네 가지 노드
DOM의 모든 요소들은 document 객체의 자식이며, 모든 요소들, 어트리뷰트, 텍스트는 하나의 객체이다.
문서노드
트리 최상단에 위치해있으며, 모든 요소 노드에 접근하기 위해서는 문서노드를 거쳐가야 한다.
요소노드
HTML요소 자체를 표현하며, 문서의 구조를 서술한다. 중첩에 의해 부모자식관계를 가지며, 이 관계를 통해 정보를 구조화한다. 모든 요소노드는 요소별 특성을 표현하기 위해 HTMLElement 객체를 상속한 객체로 구성된다.
어트리뷰트노드
HTML요소의 속성을 표현한다. 해당 속성이 지정된 요소의 자식이 아니라 해당 요소의 일부(형제)로 표현된다. 해당 요소노드를 찾아 접근하게 되면, 속성을 참조 및 수정이 가능해진다.
텍스트노드
HTML요소의 텍스트를 표현하는 최하단노드이다.
DOM 사용하기
DOM Query를 사용하기 위해 기본적으로 document 개체가 필요하다.
getElementById('id')
id속성값으로 요소노드를 한 개 선택한다. 만약 복수개가 선택되면 가장 마지막 요소를 선택한다.