본문 바로가기

Programming/국비학원

220811 - 자바스크립트 - 함수, 배열, 클로저

  • clearInterval 
  •  
const my=setInterval(() => {
    console.log('안녕하세요');
}, 3000);  //3초마다 실행

setTimeout(() => {
    clearInterval(my);
}, 7000); //7초 후 실행

 

 

 

 

  • 재귀 함수
  •  
const countdown=(value)=>{
    console.log('출력값 =',value);
    if (value===0) return value;
    return countdown(value-1); //a함수 안에서 a함수 다시 호출
}

const lastValue=countdown(10);
console.log('최종값 =',lastValue);

//
출력값 = 10
출력값 = 9
출력값 = 8
출력값 = 7
출력값 = 6
출력값 = 5
출력값 = 4
출력값 = 3
출력값 = 2
출력값 = 1
출력값 = 0
최종값 = 0

 

 

  •  
const hello=()=>{
    console.log('안녕');
    setTimeout(() => {
        hello();
    }, 2000);
}

hello();

//
함수 호출하자마자 코드 수행 & 재귀함수로 반복 

 

 

  • 문제 : 재귀함수 이용해 1~10 합 구하기
const sumNum=(start,end,accu)=>{  //accu: 누적값
    if(start>end) return accu;  //조건 부합 시 최종값 출력됨
    return sumNum(start+1,end,accu+start); //재귀함수 => 위 조건 부합될 때까지 반복
}

console.log('1~10 합 :',sumNum(1,10,0));  //55

 

 

  • 문제 : 재귀함수 이용해 팩토리얼값 구하기
const factorial=n=>{
    if (n==0) return 1;  //함수 실행 완료 시점
    return n * factorial(n-1); //5*f(4) -> 5*4*f(3) ... //반복할 구문
}

console.log('팩토리얼 결과 =',factorial(5)); //120

 

 

 

 

참고:

https://brunch.co.kr/@swimjiy/12

 

JavaScript sort() 함수 톺아보기

생각 없이 쓰던 정렬 제대로 알아보자. | 평소 코딩 테스트 준비 때문에 알고리즘 문제를 자주 풀곤 하는데, sort(), apply() 같은 메서드부터 Map, Set 같은 타입까지 자바스크립트에 내장된 다양한 문

brunch.co.kr

  • 비교 함수

기존 : Array.sort(function compare(a,b){})

 

리턴값=양수 : b-a 순서  

리턴값=음수 : a-b 순서  

리턴값=0 : 그대로

 

 

  •  
const studentList=[
    {name:'김철수',age:40,score:88},
    {name:'홍길동',age:20,score:90},
    {name:'이영희',age:40,score:58},
    {name:'박찬호',age:50,score:22},
    {name:'손흥민',age:22,score:12},      
];

studentList.sort((before,next)=>{
    if (before.age>next.age) return 1;  //1: sort(오름차순) 수행
    else if (before.age<next.age) return -1;  //-1: sort 수행 X
    else if (before.score>next.score) return -1;
    else if (before.score<next.score) return 1;  //내림차순
    return 0; //완료
});

console.log(studentList);

//
[
  { name: '홍길동', age: 20, score: 90 },
  { name: '손흥민', age: 22, score: 12 },
  { name: '김철수', age: 40, score: 88 },
  { name: '이영희', age: 40, score: 58 },
  { name: '박찬호', age: 50, score: 22 }
]

 

=>나이 오름차순, 나이 같으면 성적 내림차순

 

 

  •  
const studentList=[
    {name:'김철수',age:40,score:88},
    {name:'홍길동',age:20,score:90},
    {name:'이영희',age:40,score:58},
    {name:'박찬호',age:50,score:22},
    {name:'손흥민',age:22,score:12},      
];

const sorted=studentList.sort((before,next)=>before.age-next.age); //나이 오름차순
//before이 더 클 때 양수 -> 숫자 순서 뒤집힘
console.log(sorted);

 

 

 

 

  • slice
const names=['이영표','박지성','이동국','이순자','손흥민'];
const sliced=names.slice(1,3);  //1<=x<3  //[1~2]
console.log(sliced);

//
[ '박지성', '이동국' ]

 

 

  • 문제 : slice, sort 이용해 성적 상위 3명 출력
const studentList=[
    {name:'김철수',age:40,score:88},
    {name:'홍길동',age:20,score:90},
    {name:'이영희',age:40,score:58},
    {name:'박찬호',age:50,score:22},
    {name:'손흥민',age:22,score:12},      
];

const desc=studentList.sort((before,next)=>next.score-before.score); //내림차순
const sliced2=desc.slice(0,3);
console.log('영어 경시대회 참여 명단 :\n',sliced2);

//
영어 경시대회 참여 명단 :
 [
  { name: '홍길동', age: 20, score: 90 },
  { name: '김철수', age: 40, score: 88 },
  { name: '이영희', age: 40, score: 58 }
]

 

 

 

 

  • 클로저 (closer)

: 내부함수가 외부함수의 지역변수에 접근할 수 있는 것


=> 외부함수의 실행이 끝나 외부함수가 소멸된 이후에도 내부함수가 외부함수의 지역변수에 접근 가능 (외부함수가 리턴된 후에도 외부함수의 지역변수는 유효성 유지됨)

 

 

  •  
grandParent=(g1,g2)=>{
    const g3=3;
    return parent=(p1,p2)=>{
        const p3=33;
        return child=(c1,c2)=>{  //closer
            const c3=333;
            return g1+g2+g3+p1+p2+p3+c1+c2+c3;
        }
    }
}

const parentF=grandParent(1,2);  //parentF => granParent의 리턴 함수
const childF=parentF(11,22);
console.log(childF(111,222));  //738

 

 

  • 은닉화 (cf. 자바 - private)
function Hello(name){
    this._name=name; //필드(변수)에 접근
}

Hello.prototype.say=()=>{
    console.log(this._name+'님 안녕하세요');
}

let hello1=new Hello('홍길동');
let hello2=new Hello('김철수');
let hello3=new Hello('이영희');

hello1.say();
hello2.say();
hello3.say();

hello1._name='도적';
hello1.say();

//
홍길동님 안녕하세요
김철수님 안녕하세요
이영희님 안녕하세요
도적님 안녕하세요

 

 

=> 변수 무단으로 수정 가능

 

=> 클로저 사용

const Hello=(name)=>{
    let _name=name;
    return function(){  //익명 클로저
        console.log(_name+'님 안녕하세요')
    }
}

let hello1=Hello('홍길동');
console.log(hello1);

hello1(); //홍길동님 안녕하세요 //변수 유지됨

 

 

  • 클로저 사용 X
let num;
for (num=1;num<=10;num++){ 
//for문 10번 다 돌면 num=11 //그 후 setTimeout 실행됨
    setTimeout(() => {
        console.log(num);
    }, 1000);
}

//
11
11
11
11
11
11
11
11
11
11

 

 

  •  
let num;
for (num=1;num<=10;num++){ //for문 10번 다 돌면 num=11 //그 후 setTimeout 실행됨
    (function(num){
        setTimeout(() => {
            console.log(num);
        }, 100);
    })(num);
}

//
1
2
3
4
5
6
7
8
9
10

 

 

  • 예제 : 움직이는 알파벳
    <script>
        //랜덤 정수 리턴하는 함수
        function randomInt(limit){
            return Math.round(Math.random()*limit); //0~limit까지 숫자
        }

        //랜덤 알파벳 리턴하는 함수
        let alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
        function randomA(){
            return alphabet.charAt(randomInt(25));
        }

        //양수, 음수값으로 랜덤 속도 리턴하는 함수
        function randomSpeed(max){
            return Math.random()*max-Math.random()*max;
        }

        let canvasWidth=700;
        let canvasHeight=400;

        //글자가 이동하는 생성자 함수
        function MovingText(){
            this.x=randomInt(canvasWidth);
            this.y=randomInt(canvasHeight);
            this.vx=randomSpeed(10); //x 랜덤속도
            this.vy=randomSpeed(10); //y 랜덤속도
            this.header=document.createElement('h1');
            this.header.innerHTML=randomA();
            this.header.style.position='absolute';
            document.body.appendChild(this.header);
        }

        MovingText.prototype.move = function(){
            if (this.x<0||this.x>canvasWidth){ //정해진 구역 벗어나면 방향 바꿈
                this.vx*=-1;
            }
            if (this.y<0||this.y>canvasHeight){
                this.vy*=-1;
            }
            this.x+=this.vx;
            this.y+=this.vy;
            this.header.style.left=this.x+'px';
            this.header.style.top=this.y+'px';
        }

        window.onload=()=>{
            let moveTexts=[];
            for (let i=0;i<100;i++){
                moveTexts.push(new MovingText());
            }
            setInterval(() => {
                for (let i in moveTexts){
                    moveTexts[i].move();
                }
            }, 1000/60); //1초에 60번
        }

        //alphabet='COMPUTER';  //클로저 사용 안 해서 알파벳 마음대로 바꿀 수 잇음
    </script>

 

 

=> 클로저 사용 X

        function randomA(){
        let alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ';  //알파벳 마음대로 못 바꾸지만 메모리 낭비
            return alphabet.charAt(randomInt(25));
        }

 

 

=> 클로저 사용 O

        let randomA=(function(){
            let alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            return function(){
                return alphabet.charAt(randomInt(25));
            }
        })();

 

 

 

 

 

 

 

//

클로저가 너무 이해 안 돼서 검색을 한 시간은 한 것 같다

우선 IIFE라는 문법도 처음 봤고.. 참고한 사이트가 20개 넘을 듯

 

IIFE:

https://mine-it-record.tistory.com/m/339

 

클로저:

https://ko.javascript.info/closure
https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

https://usage.tistory.com/103

https://opentutorials.org/course/743/6544