본문 바로가기

블록체인_9기/💛 JAVASCRIPT

23강(과제X)_230406_Javascript(Set, Map, 배열메소드)

728x90

 

 


Set

  • 중복을 허용하지 않는 값을 모아놓은 특별한 컬렉션이다.
    • 배열은 중복값이 저장될 수 있지만 set은 중복이 안되는 값을 저장할 수 있다.
  • 배열은 요소의 순서에 의미가 있지만 set은 의미가 없다. 
    • 배열은 인덱스의 값으로 접근을 하지만 set은 해당 방법으로 접근이 이루어지지 않기 때문이다.
  • ES6이며, 값으로만 만들어져 있다.

주요 메소드

new Set(iterable)

  • set을 생성한다. 이터러블 객체를 전달받으면 그 안의 값을 복사해 셋에 넣어준다.

set.add(vlaue)

  • 값을 추가하고 set자기 자신을 반환한다.

set.delete(vlaue)

  • 값을 제거한다. 호출 시점에 set 내에 값이 있어서 제거에 성공하면 true를 반환, 아니면 false를 반환한다.

set.has(vlaue)

  • set내에 값이 존재하는지 확인하는 메소드이다. 확인하는 값이 존재하면 true를, 아니면 false를 반환한다.

set.clear()

  • set내의 모든 값을 제거하는 메소드이다.

set.size

  • set에 몇 개의 값이 있는지 세준다.

entries

  • 해당 메소드는 인터레이터와 인터레이블에 number 값을 부여해준다. 
  •  

//--------new Set / set.add --------------------------------------------------------------
//new Set 메서드를 이용하여 set객체를 생성하여 s1에 대입
const s1 = new Set();
//add 메서드로 값을 추가한다.
s1.add("one");
s1.add("two");
s1.add("one");   //중복 값은 허용하지 않으므로 해당 구문은 무시된다.
s1.add("three");
console.log(s1);
// 결과: Set(3) {'one', 'two', 'three'}
//----------------------------------------------------------------------------------------



//--------new Set / set.has / set.size --------------------------------------------------------------
const arr1 = [1,2,3,4,5];
//생성단계에서 생성자 함수에 배열을 전달
const s2 = new Set(arr1);

console.log(s2);
// 결과: Set(5) {1, 2, 3, 4, 5}


//has: 값을 가지고 있는지 확인하는 메소드
console.log(s2.has(2));
//결과: true

//has: set이 가지고 있는 요소를 확인하는 메소드
console.log(s2.size)
//결과: 5
//----------------------------------------------------------------------------------------



//--------set.delete / set.clear ---------------------------------------------------------

//delete: 특정 값을 제거하는 메소드
s2.delete(2);   //s2객체의 요소에서 2의 값을 가진 요소를 제거한다.
console.log(s2);
// 결과: Set(4) {1, 3, 4, 5}

//clear: 모든 값을 제거하는 메소드
s2.clear();
console.log(s2);
//결과: Set(0) {size: 0}
//---------------------------------------------------------------------------------------



//---------- entries --------------------------------------------------------------------
const arr1 = [1,2,3,4,5];
//생성단계에서 생성자 함수에 배열을 전달
const s2 = new Set(arr1);

//forEach는 이터러블 반복자이다.
s2.forEach(function(i){
    console.log(i);
    //결과: 1 2 3 4 5
})

//SetIterator 객체로 반환한다.
//entries: 이터러블의 이터레이터를 반환시켜준다.
const temp = s2.entries();
console.log(temp.next().value);
//결과: (2) [1, 1]

 

 

 


Map

  • Map은 키가 있는 데이터를 저장한다는 점에서 객체와 유사하다.
    • 다만, 맵은 키에 다양한 자료형을 허용한다는 점에서 약간의 차이가 있다.
let map = new Map();

map.set('1', 'str1');   // 문자형 키
map.set(1, 'num1');     // 숫자형 키
map.set(true, 'bool1'); // 불린형 키

// 객체는 키를 문자형으로 변환한다는 걸 기억하고 계신가요?
// 맵은 키의 타입을 변환시키지 않고 그대로 유지합니다. 따라서 아래의 코드는 출력되는 값이 다릅니다.
alert( map.get(1)   ); // 'num1'
alert( map.get('1') ); // 'str1'

alert( map.size ); // 3
  • Map객체는 키와 값을 한 쌍으로 추가해주어야 한다.
  • Map은 키의 원래 삽입순서를 기억안다.
  • 한 Map에서의 키는 오직 단 하나만 존재한다.
    • Map 집합의 유일성이다.
  • for ~ of 루프는 각 반복에 대해 [key, value]로 이루어진 멤버가 2개인 배열을 반환한다.
  • 반복은 삽입한 순서대로 발생한다.
    • 즉, set() 메서드로 맵에 처음 삽입한 각각의 키-값 순서와 대응된다.
      • 단, set()이 호출되었을 때 맵에서 해당 키가 없었을 경우에 해당된다.

주요 메소드

new Map()

  • 맵을 생성한다.

map.set(key, value)

  • key를 이용해 value를 저장한다.

map.get(key)

  • key에 해당하는 값을 반환한다.  key가 존재하지 않으면 undefind를 반환한다.

map.has(key)

  • key가 존재하면 true, 존재하지 않으면 false를 반환한다.

map.delete(key)

  • key에 해당하는 값을 삭제한다.

map.clear()

  • 맵안에 모든 요소를 제거한다.

map.size

  • 요소의 개수를 반환한다.
//--------new Map / map.set / map.get ----------------------------------------------------
//new Map메서드를 이용하여 Map객체 생성해 map변수에 대입
const map = new Map();

//값을 추가해보자!

//map.set: 메소드를 통해 키와 값을 저장한다.
//map은 값을 추가할 때 키와 같이 한 쌍으로 추가를 해줘야한다.
map.set("one",1);
map.set("one",3);       // 중복되는 키를 허용하지 않으므로, 마지막에 작성된 키가 선택된다.
map.set("two",2);
map.set("three",4);

console.log(map);
//결과: Map(3) {'one' => 3, 'two' => 2, 'three' => 4}

//키를 왜 지정할까? 키로 저장된 값을 호출하기 위해서이다.
//map.get: 메소드로 값을 호출할 수 있다.
console.log(map.get("one"));    //결과: 3
console.log(map.get("two"));    //결과: 2
console.log(map.get("three"));    //결과: 4
//----------------------------------------------------------------------------------------



//--------map.delete / map.size ----------------------------------------------------------
//delete 메소드: 삭제할 해당 키 값을 매개변수로 전달
map.delete("one");  //one키의 키값을 삭제한다.
console.log(map);
//결과: Map(2) {'two' => 2, 'three' => 4}

//사이즈 확인/ map에 저장된 요소가 몇개인지?
//size: map에 저장된 요소의 갯수를 확인할 수 있다.
console.log(map.size);
//결과: 2
//----------------------------------------------------------------------------------------



//--------map.keys / map.values ----------------------------------------------------------
//keys: map에 저장된 키값들을 전부 반환해주는 메소드
const keys = map.keys();
console.log(keys);
//결과: MapIterator {'two', 'three'}

//values: map에 저장된 벨류들을 반환해주는 메소드
const values = map.values();
console.log(values);
//결과: MapIterator {2, 4}
//----------------------------------------------------------------------------------------



//--------map.entries --------------------------------------------------------------------
//entries(): [키, 값]형태의 정보들을 모아서 MapIterator 형태로 표현
const Iter = map.entries();
console.log(Iter);
//결과: MapIterator {'two' => 2, 'three' => 4}

//next로 다음요소를 출력하므로 가장 첫 번째 요소가 나온다.
console.log(Iter.next().value);
//결과: (2) ['two', 2]
//----------------------------------------------------------------------------------------





//-------키 정보만으로 출력시키게 for of문으로 작성해보자 ----------------------------------
for (const iterator of keys) {      //map의 키들을 반환하는 객체를 사용
    //이터레이터 요소가 끝날 때까지 반복하면서 요소를 보여준다.
    console.log(iterator);
    //결과: two three
}

//값만 보여주자.
for (const iterator of values) {    //map의 값들을 반환하는 객체를 사용
    console.log(iterator);
    //결과: 2 4
}

//키랑 값을 다 출력
//구조분해 할당처럼
for (const iterator of Iter) {
    console.log(iterator);
    //결과: (2) ['two', 2]  (2) ['three', 4]
}
//이런식으로 가져올 수도 있다.
for (const [key, value] of Iter) {
    console.log(`키는 ${key}, 값은 ${value}이다아아`);
    /*결과
    키는 two, 값은 2이다아아
	키는 three, 값은 4이다아아
    */
}

//forEach문으로 키와 값을 호출할 수 있다.
map.forEach(function(value,key){
    console.log(`키는 ${key}, 값은 ${value}이다.`)
    /* 결과
    키는 two, 값은 2이다.
	키는 three, 값은 4이다.
    */
})

 


for of 명령문

  • 반복가능한 객체에 대해서 반복하고 각 개별 속성 값을 하나씩 추출하여 변수에 담아 반복문을 수행하는 문법이다.
  • 문법
//variable: 각 반복에 서로 다른 속성값이 할당된다.
//iterable: 반복되는 열거가능한 속성이 있는 객체이다.
for (variable of iterable) {
statement
}

 

 


배열메소드


래퍼런스 타입을 꼭 제대로 짚고 가야한다!

  • 참조타입은 값을 비교하는 것이 아닌, 주소를 비교하는 것이다.
// 래퍼런스 타입
let a = [1,2,3];
let b = [...a]; //값만 복사해서 새로운 배열을 만들어줌
console.log(a == b);    //결과: false -> b는 a의 값을 가지고 새로운 주소로 배열을 생성했기 때문.

let c = [5];
let d = [5];
console.log(c == d);    //결과: false -> c와 d는 각각의 배열로 동일한 값을 가지기 때문.

let e = 5;
let f = 5;
console.log(e == f);    //결과: ture

//참조타입은 값을 비교하는게 아니고 주소를 비교한다.

let g = [1,2,3,4,5];
let h = g;

h.push(2);

/* h에 push했지만 h가 g의 값을 참조하고 있기 때문에 
원본을 수정하는 push로 원본 배열의 값도 수정되는 것이다.*/
console.log(g);    // [1, 2, 3, 4, 5, 2]    
console.log(h);    // [1, 2, 3, 4, 5, 2]    
console.log(g == h);    //결과: true

 

Array.of()

  • 매개변수의 수와 자료형에 제한없이, 전달된 인자를 사용해 새 Array 인스턴스를 생성한다.
  • 배열을 생성할 때 사용하는 메소드이다.
const ex = Array.of(1,2,3,"배열");
console.log(ex);
/* 결과
Array(4)
    0: 1
    1: 2
    2: 3
    3: "배열"
    length: 4
*/

 

 

push()

  • 배열 뒷 부분에 값을 삽입한다.
  • 배열의 원본 배열을 수정하는 메소드이다.
const arr = Array.of(1,2,3,4,5,6);
arr.push(2);
console.log(arr);
//결과: (7) [1, 2, 3, 4, 5, 6, 2]
//배열에 요소를 추가할 때 push를 제외한 다른 방법으로도 추가가 가능하다. ---------------------
//자바스크립트에서는 index에러가 따로 뜨지 않는다. (정해진 사이즈가 없기 때문에)
const arr2 = [1,2,3];
//배열의 최대 인덱스는 "배열.length - 1"
//index: 0 1 2
//length: 0 1 2 3
arr2[arr2.length] = 4;  //길이는 인덱스보다 크므로 그 다음 인덱스에 값이 들어갈 수 있다.
//결과: [1, 2, 3, 4]
arr2[arr2.length + 1] = 6;  //배열의 끝에 추가하지 않고 더 이후의 인덱스에 값을 추가하면 중간값들은 비어있다.
console.log(arr2);
//결과: [1, 2, 3, 4, 비어 있음, 6]

 

 

indexOf()

  • 배열에서 지정된 요소를 찾을 수 있는 첫 번째 인덱스를 반환하고 존재하지 않으면 -1을 반환한다.
arr.indexOf(searchElement[, fromIndex])
//searchElement: 배열에서 찾을 요소
//fromIndex: optional, 기본값은 0이다. searchElement를 찾기 시작할 위치이다.
const foods = ["apple","banana","orange"];

//foods 배열에서 banana가 있는지 확인
if(foods.indexOf("grape") === -1){ //foods.indexOf("grape")에서 grape가 없으면 리턴값으로 -1을 보낸다.
    //grape가 없으면 원본에 추가해라
    foods.push("grape");
}
console.log(foods);
//결과: ['apple', 'banana', 'orange', 'grape']


const beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
console.log(beasts.indexOf('bison'));
// 결과: 1
console.log(beasts.indexOf('bison', 2));
// 결과: 4
console.log(beasts.indexOf('giraffe'));
// 결과: -1

 

includes()

  • ES 7에서 도입되었다.
  • 배열이 특정 요소를 포함하고 있는지를 판별한다.
  • 특정요소가 배열에 있으면 true, 없으면 false
const foods = ["apple","banana","orange"];

//있는지 없는지 확인할 때 사용하면 좋겠다.
if(!foods.includes("grape")){
    //없으면 추가
    foods.push("grape");
}
console.log(foods);
//결과: ['apple', 'banana', 'orange', 'grape']

 

pop()

  • 배열에서 마지막 요소를 제거하고 그 요소를 반환한다.
  • 원본이 수정되는 메소드이다.
  • 빈 배열에 pop()을 호출하면 undefined를 반환한다.
//배열의 마지막 요소를 제거하는 메소드
const arr3 = [1,2,3,4,5];
//pop: 원본이 수정되는 메소드
let poped = arr3.pop();
console.log(arr3); 
//결과: [1, 2, 3, 4]
console.log(poped); 
//결과: 5

shift()

  • 배열의 첫 번째 요소를 제거하는 메소드이다. 제거된 요소를 반환한다.
  • 빈 배열에 shift()을 호출하면 undefined를 반환한다.
  • 원본이 수정되는 메소드이다.
//배열의 마지막 요소를 제거하는 메소드
const arr3 = [1,2,3,4,5];
//shift메소드: 첫 번째 요소를 제거해준다.
arr3.shift();
console.log(arr3);
//결과: [2, 3, 4, 5]

 

concat()

  • 원본 배열을 유지한 상태로 배열을 합쳐 새로운 배열로 반환하는 메소드
  • 호출한 배열 뒤에 각 인수를 순서대로 붙여 새로운 배열을 만들어낸다.
const arr1 = [1,2];
const arr2 = [3,4];
const arr3 = arr1.concat(arr2);
console.log(arr3);
//결과: [1, 2, 3, 4]

/*concat메소드 사용 예)
	판매상품들의 리스트가 있는데 원본 배열을 수정하면 안되고,
    생활 가전 식품 리스트가 따로 있고
    우리가 전체 상품 리스트를 뽑아서 이벤트성이나
    전체 상품 페이지를 구성해야할 때
    원본은 유지하고 새로운 리스트를 만들 수 있다.
*/

 

splice()

  • 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경한다.
const arr8 = [1,2,3,4,5,6,7,8,9];

//인덱스 1부터 2개의 요소를 제거하고 해당위치에 20과 30, 40의 요소를 추가한다.
const result2 = arr8.splice(1,2,20,30,40);
console.log(arr8);
//결과: [1, 20, 30, 40, 4, 5, 6, 7, 8, 9]

console.log(result2);   //splice함수의 반환은 제거한 요소들이 반환된다.
//결과: [2, 3]


const arr9 = [1,2,3,4,5,6,7,8,9]
const result3 = arr9.splice(4,3);   //인덱스 4번부터 3개의 요소를 제거만 한다.   
console.log(arr9);      //제거한 원본 배열을 받는다.
//결과: [1, 2, 3, 4, 8, 9]
console.log(result3);   //함수의 반환값으로 제거한 요소를 받는다.
//결과: [5, 6, 7]

remove()

  • 배열에서 특정 요소를 제거하는 함수이다.
const arr10 = [1,20,3,1,50,6]
function remove(arr, item){
    //객체 insdex는 매개변수 arr로 받은 배열의 인덱스를 받는다. 
    //arr.indexOf(item) -> 매개변수로 받은 arr10에서 매개변수 item으로 받은 값을 가리키는 첫 인덱스를 반환한다. 
    const index = arr.indexOf(item);
    //indexOf에서 인덱스를 반환하면(반환하지 않는다의 부정)
    //해당 인덱스에서 하나 제거이니까 그 인덱스에 있는 요소를 제거해준다.
    if(index !== -1) arr.splice(index,1);
    return arr;
}

console.log(remove(arr10,20))
//결과: [1, 3, 1, 50, 6]

 

slice()

  • 매개변수로 전달받은 범위의 요소를 복사해서 새로운 배열 객체로 반환한다.
  • 원본 배열은 바뀌지 않는다.
  • 구문
arr.slice([begin[, end]])
  • begin
    • 0으로 시작하는 추출 시작점에 대한 인덱스를 의미한다.
    • 음수 인덱스는 배열의 끝에서부터의 길이를 나타낸다.
      • 예를들어, slice(-2)라면 배열의 마지막 두 개의 엘리먼트를 추출한다.
    • begin이 undefined일 경우에는 0번 인덱스부터 추출한다.
    • begin이 배열의 길이보다 큰 경우에는 빈 배열을 반환한다.
  • end
    • 추출을 종료할 0기준의 인덱스이다.
    • slice는 end인덱스를 제외하고 추출한다.
    • 음수 인덱스는 배열의 끝에서부터의 길이를 나타낸다.
    • 예를들어, slice(2, -1)이라면 배열의 세 번째 요소부터 끝에서 두 번째 요소까지 추출한다.
    • end가 생략되면 slice 배열의 끝까지 추출한다.
    • end의 값이 배열의 길이보다 크다면 slice는 배열의 끝까지 추출한다.
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];

//end가 생략되면 slice 배열의 끝까지 추출한다.
console.log(animals.slice(2));
// 결과: Array ["camel", "duck", "elephant"]

//첫 매개변수: 0으로 시작하는 추출 시작점에 대한 인덱스를 의미한다.
//두번째 매개변수: slice는 end인덱스를 제외하고 추출한다.
console.log(animals.slice(2, 4));
// 결과: Array ["camel", "duck"]

//end의 값이 배열의 길이보다 크다면 slice는 배열의 끝까지 추출한다.
console.log(animals.slice(1, 5));
// 결과: Array ["bison", "camel", "duck", "elephant"]

//음수 인덱스는 배열의 끝에서부터의 길이를 나타낸다.
console.log(animals.slice(-2));
// 결과: Array ["duck", "elephant"]
console.log(animals.slice(2, -1));
// 결과: Array ["camel", "duck"]

//begin이 undefined일 경우에는 0번 인덱스부터 추출한다.
//end가 생략되면 slice 배열의 끝까지 추출한다.
console.log(animals.slice());
// 결과: Array ["ant", "bison", "camel", "duck", "elephant"]

 

join()

  • 배열의 모든 요소를 연결해 하나의 문자열로 만든다.
const arr12 = [1,2,3,4];
const result4 = arr12.join();
console.log(result4);
//결과: 1,2,3,4


//----------여러가지 방법으로 배열 연결하기 ----------------------------------------
var a = ['바람', '비', '불'];
var myVar1 = a.join();     
console.log(myVar1);
//결과: 바람,비,불
var myVar2 = a.join(', ');  
console.log(myVar2);
//결과: 바람, 비, 불
var myVar3 = a.join(' + '); 
console.log(myVar3);
//결과: 바람 + 비 + 불
var myVar4 = a.join('');
console.log(myVar4);
//결과: 바람비불
//--------------------------------------------------------------------------------

 

 

reverse()

  • 배열의 순서를 반전시킨다.
  • 첫 번째 요소는 마지막 요소가 되고, 마지막 요소는 첫 번째 요소가 된다.
const arr = [1,2,3,4,5];

console.log(arr.reverse());
//결과: [5, 4, 3, 2, 1]

 

fill()

start나, end가 음수일 경우. (출처: https://hianna.tistory.com/399)

  • 배열의 시작 인덱스부터 끝 인덱스의 이전까지 정적인 값 하나로 채운다.
  • 배열의 갯수는 유지하되, 배열의 값을 초기화 해야할 때 사용할 수 있다.
  • 구문
arr.fill(value[, start[, end]])
  • value: 배열을 채울 값
    • value에 객체를 받을 경우 그 참조만 복사하여 배열을 채운다.
  • start: optional. 시작 인덱스이다. 기본값은 0이다.
    • start가 음수이면 시작 인덱스는 length + start이다.
  • end: optional. 끝 인덱스이다. 기본값은 this.length이다.
    • end가 음수이면 시작 인덱스는 length + end이다.
const arr = [1,2,3,4,5];

arr.fill(4);    //start와 end값이 정해지지 않았으므로 배열의 전부를 value값으로 채운다.
console.log(arr);
//결과: [4, 4, 4, 4, 4]

arr.fill(4, 1);   //인덱스 1번부터 4로 채운다.
console.log(arr);
//결과: [1, 4, 4, 4, 4]

arr.fill(4, 1, 3);  //인덱스 1번부터 인덱스 2번까지 4로 채운다.
console.log(arr);
//결과: [1, 4, 4, 4, 5]

arr.fill(4, 1, 1);  //인덱스 1번부터 인덱스 0번까지 이므로, 조건이 부합하지 않아서 변경X
console.log(arr);
//결과: [1, 2, 3, 4, 5]

//위치값이 음수이므로, length -로 진행
arr.fill(4, -3, -2);    //따라서 인덱스 2부터 인덱스 2번까지(end 이전 값) 4로 채운다.
console.log(arr);
//결과: [1, 2, 4, 4, 5]

flat()

  • 모든 하위 배열 요소를 지정한 깊이까지 재귀적으로 이어붙인 새로운 배열을 생성한다.
  • ES10에서 도입되었다.
  • 구문
const newArr = arr.flat([depth])
  • depth: 중첩 배열 구조를 평탄화할 때 사용할 깊이 값. 기본값은 1이다.
//flat() 메소드 : 배열의 뎁스를 1차 배열로 맞춰준다.
const arr1 = [1,[2,3,4],[1,3]].flat(); //한 뎁스씩 올려서 맞춰준다.

const arr2 = [1,[2,[3],4],[1,[3]]].flat(2);    //매개변수로 뎁스의 갯수를 넣어주면 적용된다.

const arr3 = [[1,[2,[[3,[4]]]]]].flat(Infinity); //뎁스가 몇 개든지 전부 꺼내준다.
console.log(arr1);
//결과: [1, 2, 3, 4, 1, 3]
console.log(arr2);
//결과: [1, 2, 3, 4, 1, 3]
console.log(arr3);
//결과: [1, 2, 3, 4]

 

 

 


👩‍🏫예시_클릭하면 옆에서 열리는 애니메이션 영역 만들기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button class="drawer-opener">열기</button>
    <div class="drawer">
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
        </ul>
    </div>
</body>
<script>
    
//open에 전달된 매개변수가 없으면 open에 디폴트로 false 값이 들어간다.
//매개변수의 디폴트값 설정
function Drawer(el, open = false){
    this.el = el;
    this.isOpen = open;
    //객체의 원형에 assign 메소드는 하나 이상의 객체로부터 
    //대상 객체로 속성을 복사할 때 사용한다.
    //두 번째 매개변수는 객체의 속성을 복사해서 첫 번째 매개변수의
    //객체에 속성을 추가한 뒤 첫 번째 매개변수의 객체를 반환한다.
    
    //따라서, 사용법은 다른 객체의 속성을 복사해서 새로운 객체를 생성한다.
    Object.assign(this.el.style, {
        display: "block",
        position: "fixed",
        top: 0,
        bottom: 0,
        right: 0,
        width: "500px",
        padding: "10px",
        backgroundColor: "yellow",
        transition: "1s"
    });
}

Drawer.prototype.open = function(){
    this.isOpen = true;
    this.el.style.transform = "translate(0px)";
}

Drawer.prototype.close = function(){
    this.isOpen = false;
    this.el.style.transform = "translate(500px)";
}

const sideMenu = new Drawer(document.querySelector(".drawer"));

document.querySelector(".drawer-opener").onclick = function(){
    if(!sideMenu.isOpen){
        sideMenu.open();
    }
    else{
        sideMenu.close();
    }
}
</script>
</html>

 

 

 

 

더보기

 

728x90