TIL 0405

먼지·2024년 4월 5일

Today I Learned

목록 보기
35/89
post-thumbnail

배열

배열은 순서가 있는 요소의 집합. 자바스크립트 배열의 길이는 가변적이다. 요소를 말미에 더하면 배열의 길이가 자동으로 늘어난다.

정렬

sort 메서드를 이용하면 배열의 요소 값을 정렬할 수 있다. 인자 없이 sort 메서드를 호출하면 문자열 기준으로 정렬. 문자열 정렬은 Unicode의 코드 포인트 값의 대소 비교를 통해 이루어진다.

배열 요소의 정렬

array.sort(); => 오름차순 정렬
array.reverse(); => 반대로 정렬
문자열을 오름차순 정렬할 때는 문제가 없는데 숫자를 할 때는 문제가 발생함
숫자를 문자열로 인식하여 채

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>배열 요소의 정렬</title>
</head>
<body>
    <script>
        const array = ['가', '하', '아', '나'];
        //배열 요소의 목록
        document.write(array + '<br>');

        array.sort(); //오름차순 정렬
        document.write(array + '<br>');

        array.reverse(); //반대로 정렬
        document.write(array + '<br>');
        document.write('-----------<br>');

        const array2 = [52,273,102,32];
        document.write(array2 + '<br>');

        //오름차순 정렬
        //array2.sort(); //숫자의 배열인데 문자열로 인식하여 앞자리로만 정렬
        //익명 함수
        array2.sort(function(left, right) { 
        //함수를 이용해 연산을 시키면 숫자로 인식하기 때문에 정렬이 가능함
            return left - right;
        });
        document.write(array2 + '<br>');


        array2.sort(function(left,right) {
        // 내림차순 정렬, 오름차순의 식의 반대로
            return right - left;
        });
        document.write(array2 + '<br>');

    </script>
</body>
</html>

문자열 정렬

var arr = [‘one’,’two’,’three’,’four’,’five’,’six’];
arr.sort();
[‘five’,’four’,’one’,’six’,’three’,’two’]

숫자 배열 정렬

var arr = [1,0,20,100,55];
arr.sort(function(a,b){
  return a - b;
});
[0,1,20,55,100]

배열의 메소드 사용

join() : 배열의 요소 전체를 쉼표 구분자로 반환
slice() : 지정한 인덱스 범위의 데이터를 추출해서 배열로 반환
concat() : 전달한 인자를 이용해서 새로운 배열 생성 반환

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>배열의 메소드 사용</title>
</head>
<body>
    <script>
    const array = ['파도', '하늘', '도시', '구름'];
    //배열 요소의 목록 출력
    document.write(array+'<br>');
    
    document.write('array.join() : ' + array.join() + '<br>');
    // 구분자를  -로 변경시킴
    document.write('array.join("-") : ' + array.join('-') + '<br>');

    //지정한 인덱스부터 마지막 인덱스까지의 데이터를 추출해서 배열로 반환
    document.write('array.slice(2) : ' + array.slice(2) + '<br>');
    //시작 인덱스부터 끝 인덱스 전까지 
    document.write('array.slice(1,3) : ' + array.slice(1,3) + '<br>');

    // 문자열을 인자로 전달해서 새로운 배열 반환
    document.write('array.concat("서울", "부산") : ' + array.concat('서울' , '부산',) + '<br>');
    // 배열을 인자로 전달해서 새로운 배열 반환
    document.write('array.concat( ["한국" , "미국] ) : ' + array.concat( ['한국' , '미국'] )+'<br>');

</script>
</body>
</html>

메소드를 이용한 배열 요소 삽입 / 삭제

push () : 배열 객체 마지막에 새 데이터를 삽업
pop() : 배열에 저장된 데이터 중 마지막 인덱스에 저장된 데이터를 삭제
shift(): 배열 객체에 저장된 데이터 중 첫 번째 인덱스에 지정된 데이터를 삭제
unshift() : 배열 객체의 가장 앞의 인덱스에 새 데이터를 삽입
---> 제거하는 것이 명확하다면 훨씬 사용에 용이할 수 있다. (맨 앞, 맨 뒤 삭제)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>메소드를 이용한 배열 요소의  삽입/삭제</title>
</head>
<body>
    <script>
        const array=[];
        array.push(10,20,30); // 배열의 요소 삽입
        //배열 요소의 목록 출력
        document.write(array + '<br>');

        array.push(40); //삽입
        document.write(array + '<br>');

        //배열의 시작에 새 값을 추가
        array.unshift('melon'); //인덱스의 변동이 생김
        document.write(array + '<br>');
        document.write('----------------------<br>');

        //배열의 마지막 요소 삭제
        array.pop();
        document.write(array + '<br>');

        //배열의 시작에서 값 제거하기
        array.shift();
        document.write(array + '<br>');
    </script>
    
</body>
</html>

요소의 생성, 제거

var arr = [];
arr.push(요소);
var arr = [‘zero’,’one’,’xxx’,’two’,’three’];
delete arr[2];
zero,one,,two,three    //두 번째 인덱스에 해당하는 요소는 빈 그대로 남음

arr.splice(2,1); //두 번째 인덱스에 해당하는 요소부터 하나의 요소를 제거
zero,one,two,three

indexOf 함수

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>indexOf</title>
</head>
<body>
    <script>
        const array = [10,20,30,40,50,50,40,30,20,10];

        //요소를 인자로 전달하면 해당 요소의 인덱스 반환
        let output1 = array.indexOf(40);
        document.write(output1 + '<br>');

        //요소에 해당 인자가 없으면 -1 반환
        let output2 = array.indexOf(80);
        document.write(output2 + '<br>');

        // 배열 요소 뒤부터 인자 찾기
        let output3 = array.lastIndexOf(40);
        document.write(output3 + '<br>');

        // 요소에 해당하는 인자가 없다면 항상 -1 반환시킴
        let output4 = array.lastIndexOf(80);
        document.write(output4 + '<br>');
    </script>
</body>
</html>

forEach 함수

element : 배열에 저장된 요소
index : 요소의 인덱스
array : 사용 중인 배열 객체

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width= , initial-scale=1.0">
    <title>forEach</title>
</head>
<body>
    <script>
        const array = [1,2,3,4,5,6,7,8,9,10];
        
        let sum = 0;
        //배열의 요소에 접근해서 반복 처리할 수 있는 메소드
        array.forEach(function(element, index,array){
            //배열 요소의 총합
            sum += element;

            document.write(index + ':' + element + '->' + sum + '<br>');
            document.write('배열 객체 : ' + array + '<br>');
        });
        document.write('-------------<br>');
        document.write('배열 요소의 합계 : ' + sum);
    </script>
</body>
</html>

Filter 함수

filter() : 특정 조건을 만족하는 새로운 배열을 만들 때 사용
return 할 때 조건식을 넣어줌

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>filter</title>
</head>
<body>
    <script>
        //
        const array = [1,2,3,4,5,6,7,8,9,10];

        //5이하의 데이터를 새로운 배열에 담아서 반환
        const new_array = array.filter(function(element,index,array){
                //조건
            return element <= 5;
        });

        document.write(new_array);
        
    </script>
</body>
</html>

Map 함수

map() : 값을 새롭게 정의한 후 새로운 배열을 만들어 반환
return에 계산식을 넣어줌, 만약 조건식이 들어왔다면 true or false가 반환되었을 것임

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Map</title>
</head>
<body>
    <script>
        const array = [1,2,3,4,5,6,7,8,9,10];

        //요소 * 요소 값이 저장된 배열 반환
        const new_array = array.map(function(element,index,array){
                        //계산식
            return element * element; // 조건식이 들어왔다면 true, false가 반환될것임
        });

        document.write(new_array);
    </script>
</body>
</html>

실습 문제

정수를 prompt로 5번 입력 받아서 배열에 저장시킨다. 저장된 데이터 중에서 최대값 과 최소값을 구하여 출력하세요.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>실습</title>
</head>
<body>
    <script>
        const score = [];
	
	for(let i=1;i<=5;i++){
		score.push(Number(prompt(i + '번 숫자 입력:','')));
	}
	
	document.write(score + '<br>');
	
	let max = score[0], min = score[0];
	/*
	for(let i=1;i<score.length;i++){
		if(max < score[i]){
			max = score[i];
		}
		if(min > score[i]){
			min = score[i];
		}
	}
	*/
	/*
	for(let i in score){
		if(max < score[i]){
			max = score[i];
		}
		if(min > score[i]){
			min = score[i];
		}
	}
	*/
	score.forEach(function(element,index,array){
		if(max < element){
			max = element;
		}
		if(min > element){
			min = element;
		}
	});
	
	document.write('최대값 : ' + max + '<br>');
	document.write('최소값 : ' + min);
	
    </script>
</body>
</html>

객체 생성하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>객체 생성</title>
</head>
<body>
    <script>
        //객체 생성
        const product = {
            //속성(key : value)
            제품명 : '캐스피',
            제품번호 : 'A1001',
            기능 : 'Hi Speed',
            원산지: '대한민국',
            가격: 1000,
            업데이트지원 : true
        }

        document.write(product.제품명);
        document.write('<br>');
        document.write(product.가격);
        document.write('<br>');
        document.write(product['업데이트지원']);
        document.write('<br>');
        document.write(product['기능']);
        document.write('<br>----------<br>')
        const country = {
            '행정 수도' : '서울',
            '인구수~' : 10000
        };
        document.write(country['행정 수도']);
        document.write('<br>');
        document.write(country['인구수~']);
    </script>
</body>
</html>

반복문을 이용한 객체의 속성 읽기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>반복문을 이용해서 객체의 속성 읽기</title>
</head>
<body>
    <script>
        const product = {
            name: 'eclipse',
            price : '10,000원',
            language : '한국어',
            supportOS:'win10',
            subscription : true
        }

        //for in 반복문
        for(let key in product) {
            document.write(key + ':' + product[key] + '<br>');
        }

    </script>
</body>
</html>

객체의 속성과 메소드 사용

this : 메서드 내에서 자기 자신이 가지고 있는 속성(또는 메소드)를 호출하고 싶을 때 객체 내부에서 객체를 참조한다는 의미
this.name 형식으로 속성 호출
this.name이 아니라 name을 호출하면 메소드 내에
선언한 지역 변수를 찾고 없을 경우 객체 밖에 선언된 변수를 찾음

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>객체의 속성과 메소드 사용</title>
</head>
<body>
    <script>
        //let name = '장영실';
        //객체 생성
        const person = {
            //속성 지정
            name : '홍길동',
            //메소드 지정
            eat : function(food){
               // let name = '이순신';
                //document.write(name + '이 ' + food + '을 먹습니다.<br>') 
                // name이 외부에 지정되면 해당 name의 값 출력함
                // 메소드 내에 선언되면 매소드 내에 선언된 name의 값 출력함
                document.write(this.name + '이 ' + food + '을 먹습니다.<br>')
            }
        };
        //객체의 속성 호출
        document.write(person.name);
        document.write('<br>');
        //객체의 메소드 호출
        person.eat('밥');
    </script>
</body>
</html>

빈 객체에 속성 추가하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>빈 객체에 속성 추가</title>
</head>
<body>
    <script>
        const student = { };

        //객체에 속성 추가
        student.이름 = '홍길동'
        student.취미 = '악기';
        student.특기 = '프로그래밍';
        student.장래희망 = '프로그래머';

        //in 키워드를 이용해서 객체 내의 속성 존재 여부를 체크
        document.write(('특기' in student) + '<br>');
        document.write(student.이름 + '<br>');
        document.write(student.취미 + '<br>');
        document.write('-----------------<br>');

        //객체에 메서드 추가
        student.play = function() {
            document.write('피아노를 연주하다');
        };
        //생성한 메서드 호출
        student.play();
        document.write('<br>-----------------<br>');

        //for in 반복문을 이용해서 객체의 속성과 메서드 출력
        for (let key in student) {
            document.write(key + ':' + student[key] + '<br>');
        }
    </script>
</body>
</html>

Method

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Method</title>
</head>
<body>
    <script>
        //ES6부터 function키워드를 생략한 축약 표현을 사용 가능
        //객체 생성
        const obj = {
            //속성 지정
            name : 'Peter',
            play:function() {
                document.write('열심히 일하다');
            },
            //메소드 축약 표현
            sayHi(){
                document.write('Hi! ' + this.name);
            }
        };
        obj.sayHi();
    </script>
</body>
</html>

to String

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>to String</title>
</head>
<body>
    <script>
        //빈 객체 생성
        const student = {};
         document.write(student);
         document.write('<br>');
         document.write(student.toString() + '<br>');
         document.write('-----------------<br>');

         //객체에 속성 추가
         student.이름 = '박문수';
         student.취미 = '악기';
         student.특기 = '프로그래밍';

         //객체에 메소드 추가
         student.toString = function(){
            let msg = '';
            for(let key in student) {
                if(key != 'toString'){ // tostring 제외시키기
                msg += key + ':' + student[key] + '<br>';
            }
        }
            return msg;
         }
         document.write(student.toString() + '<br>');
         document.write('-----------------<br>');
         document.write(student);
    </script>
</body>
</html>

속성 제거

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>속성 제거</title>
</head>
<body>
    <script>
        // 객체 생성
        const student = {
            // 속성 지정
            이름: '박문수',
            나이: 40,
            직업: '변호사',
            주소: '서울시'
        };
        // toString 메서드 지정
        student.toString = function() {
            let output = ''; // 수정: 빈 문자열로 초기화
            for (let key in this) {
                // toString은 제외
                if (key != 'toString') {
                    output += key + ' : ' + this[key] + '<br>'; // 수정: += 연산자로 문자열 추가
                }
            }
            return output;
        };
        // 객체의 속성 목록 출력
        document.write(student.toString() + '<br>');

        // 속성 제거
        delete student.나이;
        document.write(student.toString());
    </script>
</body>
</html>

배열에 객체 저장

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>배열에 객체 저장</title>
</head>
<body>
    <script>
        //빈 배열 생성
        const students = [];
        //객체를 배열에 저장
        students.push({이름 : '김수현', 국어 : 100, 영어 : 99, 수학 : 98, 과학 : 95});
        students.push({이름 : '이동욱', 국어 : 99, 영어 : 99, 수학 : 98, 과학 : 95});
        students.push({이름 : '공유', 국어 : 98, 영어 : 99, 수학 : 98, 과학 : 95});
        students.push({이름 : '김지원', 국어 : 88, 영어 : 99, 수학 : 98, 과학 : 95});
        students.push({이름 : '박민영', 국어 : 77, 영어 : 99, 수학 : 98, 과학 : 95});

        //students 배열 내의 모든 객체에 메소드 추가
        for(let i in students){
            //총점 구하는 매소드 추가
            students[i].getSum = function() {
                return this.국어 + this.영어 + this.수학 + this.과학;
            };
            //평균 구하는 메소드 추가
            students[i].getAverage = function() {
                return this.getSum() / 4;
            }
        }
        //배열에 저장된 객체들의 속성 및 메서드 호출
        document.write('이름 , 총점, 평균<br>');
        for(let i in students){
            document.write(
            students[i].이름+','+
            students[i].getSum()+ ',' + 
            students[i].getAverage() + '<br>');
        }
    </script>
</body>
</html>

실습 문제

이름 | 수입 | 지출 | 세금(5%, getTax()) | 잔액(getBalance(), 세금 공제)
홍길동 3000 2500
박문수 5000 1100
이순신 4000 3600
김유신 7000 4200

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>실습</title>
</head>
<body>
    <script>
       //  배열  생성
       const person = [];
       person.push({이름 : '홍길동', 수입 : 3000, 지출 : 2500});
       person.push({이름 : '박문수', 수입 : 5000, 지출 : 1100});
       person.push({이름 : '이순신', 수입 : 4000, 지출 : 3600});
       person.push({이름 : '김유신', 수입 : 7000, 지출 : 4200});

        //person 배열 내의 모든 객체에 메소드를 추가시킨다
        for (let i in person){
            //세금 구하는 메소드 추가
            person[i].getTax = function(){
                return this.수입 * 0.05;
            }
            // 잔액 구하는 메소드 추가
            person[i].getBalance = function() {
                return this.수입 - this.지출 - this.getTax() ;
            }
        }
        document.write('이름, 수입, 지출, 세금, 잔액 <br>');
        for(let i in person){
            document.write(
                person[i].이름 + ',' +
                person[i].수입 + ',' +
                person[i].지출 + ',' +
                person[i].getTax() + ',' +
                person[i].getBalance()  + '<br>'
            );
        }
    </script>
</body>
</html>

생성자 함수 생성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>생성자 함수 생성</title>
</head>
<body>
     <script>
        //생성자 함수 정의
        function Animal (name, age){
            //속성 지정
            this.name = name;
            this.age = age;
            
            //메소드
            this.eat = function() {
                document.write('맛있는 먹이를 먹습니다.');
            };
        }
        //객체 생성
        const animal = new Animal('비둘기' , 10);
        //속성 호출
        document.write(animal.name + '<br>');
        document.write(animal.age + '<br>');
        
        //메소드 호출
        animal.eat();
        
     </script>
</body>
</html>

생성자 함수 사용

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>생성자 함수 사용</title>
</head>
<body>
    <script>
        function Student(name, korean, math, english, science){
            this.name = name;
            this.korean = korean;
            this.math = math;
            this.english = english;
            this.science = science;

            //메서드 지정
            this.getSum = function()    {
                return this.korean + this.math + this.english + this.science;
            };

            this.getAvg = function() {
                return this.getSum() / 4;
            };

            this.toString = function()  {
                return this.name + ', ' + this.getSum() + ', ' + this.getAvg();
            };
        }

        //생성자 함수를 이용한 객체 생성
        const student = new Student('홍길동', 99,98,97,99);

        document.write(student + '<br>');
    </script>
</body>
</html>

배열에 객체 저장

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>배열에 객체 저장</title>
</head>
<body>
    <script>
        //생성자 함수 정의
        function Student(name, kor, math, eng, science){
            this.name = name;
            this.kor = kor;
            this.math = math;
            this.eng = eng;
            this.science = science;
            
            this.getSum = function()    {
                return this.kor + this.math + this.eng + this.science;
            };

            this.getAvg = function() {
                return this.getSum() / 4;
            };

            this.toString = function()  {
                return this.name + ', ' + this.getSum() + ', ' + this.getAvg();
            };
        }

        //배열 생성
        const students = [];
        // 배열에 객체 저장
        students.push(new Student('홍길동',99,98,97,99));
        students.push(new Student('박문수',100,98,97,99));
        students.push(new Student('장영실',99,94,97,99));
        students.push(new Student('강호동',99,93,97,99));
        students.push(new Student('유재석',99,100,97,99));

        // 출력
        document.write('이름, 총점 , 평균<br>');
        for(let i in students){
            document.write(students[i].toString() + '<br>');
        }
    </script>
</body>
</html>

Prototype

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>배열에 객체 저장</title>
</head>
<body>
    <script>
        //생성자 함수 정의
        function Student(name, kor, math, eng, science){
            this.name = name;
            this.kor = kor;
            this.math = math;
            this.eng = eng;
            this.science = science;

            //프로토타입은 생성자 함수를 사용해 생성된 객체가 공통으로 가지는 공간
            Student.prototype.getSum = function() {
                return this.kor + this.math + this.eng + this.science;
            };
            Student.prototype.getAvg = function () {
                return this.getSum() / 4;
            };
            Student.prototype.toString = function() {
                return this.name + ', ' + this.getSum() + ', ' + this.getAvg();
            };
        }

        //배열 생성
        const students = [];
        // 배열에 객체 저장
        students.push(new Student('홍길동',99,98,97,99));
        students.push(new Student('박문수',100,98,97,99));
        students.push(new Student('장영실',99,94,97,99));
        students.push(new Student('강호동',99,93,97,99));
        students.push(new Student('유재석',99,100,97,99));

        // 출력
        document.write('이름, 총점 , 평균<br>');
        for(let i in students){
            document.write(students[i].toString() + '<br>');
        }
    </script>
</body>
</html>

상속

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>상속</title>
</head>
<body>
    <script>
        //자바스크립트는 프로토타입을 이용해서 상속 구현
        function Human(age){
            this.age = age;
        }
        Human.prototype.type = '사람';
        Human.prototype.getType = function() {
            return this.type;
        };
        Human.prototype.getAge = function() {
            return this.age;
        };

        const human = new Human(20);
        document.write('human.type = ' + human.type + '<br>');
        document.write('human.age = ' + human.age + '<br>');
        document.write('human.getType = ' + human.getType() + '<br>');
        document.write('human.getAge = ' + human.getAge());
        document.write('<br>-------------------------<br>');

        //자식 생성자 함수 정의
        function Student(age){
            this.age = age;
        }
        //휴먼의 프로토타입을 학생 프로토 타입에 복사를 시키는 것
        Student.prototype = Human.prototype;
        //프로토 타입의 생성자를 재정의(정의하지 않아도 구동상의 문제가 없다.)
        Student.prototype.constructor = Student;

        //Human을 상속받은 Student 객체 생성
        const student = new Student(40);
        document.write('student.type = ' + student.type + '<br>');
        document.write('student.age = ' + student.age + '<br>');
        document.write('student.getType = ' + student.getType() + '<br>');
        document.write('student.getAge = ' + student.getAge());
    </script>
</body>
</html>
profile
Lucky Things🍀

0개의 댓글