수업


재귀함수


(사진 출처: 나무위키)

재귀함수:
내가 나를 호출하는 것이다.
가독성이 떨어지기 때문에 실무에서 권하지는 않는다.

  1. 종료조건 체크

  2. 반복문으로 구현할 수 있는 것은 재귀함수로 모두 구현 가능하고
    재귀함수로 구현 가능한 것은 반복문으로 대부분(복잡도를 증가시키면 모두) 구현 가능하다.


factorial()*

factorial(n) = n * factorial(n-1) 혹은 풀어서 쓰자면,
factorial(n) = n * (n-1) * (n-2) * ... * 1라고 표현할 수 있다.

1부터 n까지의 모든 수를 곱한 것이다.

 function factorial(n){
        if(n <= 1){
            return n
        }
        return n * factorial(n-1)
    }

factorial(5)는 아래의 과정을 통해 120이라는 값이 출력된다.

    factorial(5) == 5 * factorial(4) == 5*24 == 120
    factorial(4) == 4 * factorial(3) == 4*6
    factorial(3) == 3 * factorial(2) == 3*2
    factorial(2) == 2 * factorial(1) == 2*1
    factorial(1) == 1

sigma

sigma(n) = n + sigma(n-1)혹은 풀어서 쓰자면,
sigma(n) = n + (n-1) + (n-2) + ... + 1라고 표현할 수 있다.

function sigma(n){
        if(n <= 1){
            return n
        }
        return n + sigma(n-1)
    }

sigma(5)는 아래의 과정을 통해 15라는 값이 출력된다.

sigma(5) == 5 + sigma(4) == 5+10 == 15
sigma(4) == 4 + sigma(3) == 4+6
sigma(3) == 3 + sigma(2) == 3+3
sigma(2) == 2 + sigma(1) == 2+1
sigma(1) == 1

재귀함수를 이용한 문자열 뒤집기*

function reverse(text) {
    text += '' 
    if(text.length <= 1){
        return text
    }
    return reverse(text.slice(1)) + text[0]
}
reverse('hello') 
-> 'olleh'

text += ''를 처음에 써줘서 텍스트가 숫자가 쓰일 상황을 대비해 안전하게 문자열로 바꿔준다.
만약 텍스트의 길이가 1보다 작거나 같으면, 텍스트 그대로 출력한다.
아니라면, 텍스트의 길이가 1이 될 때까지,

(텍스트의 첫 글자가 잘린 나머지) + (텍스트의 첫글자)를 반복한다.

아래의 과정을 통해 'hello'라는 문자열이 'olleh'라는 문자열로 뒤집혀서 출력된다.

    reverse('hello') == reverse('ello') + 'h' == 'olle' + 'h'
    reverse('ello') == reverse('llo') + 'e' == 'oll' + 'e'
    reverse('llo') == reverse('lo') + 'l' == 'ol' + 'l'
    reverse('lo') == reverse('o') + 'l' == 'o' + 'l'
    reverse('o') == 'o'
 

피보나치 함수*

1 1 2 3 5 8 13 21 34 ...
fibo(n) = fibo(n-1) + fibo(n-2) 라고 할 수 있다.

function fibo(n){
	if(n <= 2){
		return n
	}
	return fibo(n-1) + fibo(n-2)
}

왼쪽 function만 따라온다.

fibo(4) == fibo(3) + fibo(2) == 3 + 2
fibo(3) == fibo(2) + fibo(1) == 2 + 1
fibo(2) == 2
fibo(1) == 1

함수는 리턴해주면 휘발되기 때문에 fibo(4)를 할 시점에서는 최종적으로 남는 값이 fibo(3)밖에 없다. 그래서 fibo(2)를 다시 계산해 주어야 한다.
하지만 계속 이렇게 새로 호출해주면 효율이 안 좋다.
(사진 출처: 위키피디아)

이걸 해결하기 위해 다이나믹 프로그래밍(메모이제이션, 타뷸레이션) 등을 적절히 사용할 필요가 있다.

inindex의 값이다.

3 in [1, 2, 3]
-> false
3 in [1, 1, 1, 1]
-> true

in연산자 - mozilla 참고링크:
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/in




즉시실행함수


즉시실행함수

  1. 즉시 실행하고 외부에서 컨트롤할 필요가없는 함수
  2. function scope, 메모리 효율

익명 즉시 실행 함수

    (function () {
        let a = 1;
        let b = 2;
        return a + b;
    }());

기명 즉시 실행 함수

    (function foo() {
        let a = 3;
        let b = 5;
        return a * b;
    }());

    foo(); 
    -> ReferenceError: foo is not defined

기명 즉시 실행 함수는 어차피 실행하지 못해서 의미가 없다.

메모리를 효율적으로 관리하기 위해 바로 실행해야 하는 것들을 즉시 실행함수로 관리한다.

map*

    let data = [{
        반 : 1, 
        번 : 1, 
        이름 : "호준", 
        중간고사점수 : 55
    }, {
        반 : 1, 
        번 : 2, 
        이름 : "길동", 
        중간고사점수 : 60
    }, {
        반 : 1, 
        번 : 3, 
        이름 : "영희", 
        중간고사점수 : 30
    }, {
        반 : 1, 
        번 : 4, 
        이름 : "철수", 
        중간고사점수 : 20
    }, {
        반 : 1, 
        번 : 5, 
        이름 : "규리", 
        중간고사점수 : 100
    }]
    data.map(x => x.중간고사점수)
    -> (5) [55, 60, 30, 20, 100]

map을 사용하면, 정보를 뽑아내는게 간단하다.

    data.map(x => [x.이름, x.중간고사점수])
    -> [Array(2), Array(2), Array(2), Array(2), Array(2)]
    // 0: (2) ['호준', 55]
    // 1: (2) ['길동', 60]
    // 2: (2) ['영희', 30]
    // 3: (2) ['철수', 20]
    // 4: (2) ['규리', 100]

중간고사 합계↓

    let s = 0;
    data.map(x => x.중간고사점수).forEach(y => s+= y)
    //x => x.중간고사점수
    //y => s+=y이게 콜백함수
    
    s
    -> 265

forEach (콜백함수)

forEach- mozilla 참고링크: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

콜백함수: forEach처럼 함수의 매개변수로 함수를 받게 되면 그때 괄호 안에 들어가는 함수가 콜백함수

2차원배열

let data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let newData = data.map(a => a.map(n => n *2));

배열이 두개 있어서 맵을 두번 사용했다.
여기서 a는 [1,2,3] 안에 있는 숫자를 두배로 해서(n => n*2) 넣어준다.




Call by Value


자바스크립트는 모두 call by value이다. call by reference는 없다.
call by value는 참조값에 대한 복사본을 만들어서 넘긴다.

다만, arrayobjectindex로 메모리 주소를 따라가 값을 처리하는데 여기에서는
주소값이 재할당된 것이 아니고 속성이 변경된 것이어서 call by reference처럼 보이는 것뿐이고, 실제로는 그냥 call by value이다.

여러가지 값이 들어가 있는 것은 변경 된다.(array, object, function)

	let x = [10, 20, 30]
	function test(a) {
     	   a[0] = 10000;
  	  }
   	 test(x)
   	 x
   	 -> (3) [10000, 20, 30]
  	let x = 10;
  	function test(a) {
 	     a[0] = 10000;
	  }
 	 test(x)
 	x
	-> 10

arrayobject를 넘길 때는 주의를 해야한다!




filter

filter - mozilla 참고링크: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

   mdn 예제
   
   const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
   const result = words.filter(word => word.length > 6);
   console.log(result);
   -> (3) ['exuberant', 'destruction', 'present']
   //true인 것만 가져온다.
   
   let x = [2, 6, 5, 4, 8, 5, 4, 3, 2, 9]
   x.filter(z => z > 5);
   -> (3) [6, 8, 9]
   
   // 5를 초과하는 숫자만

로그인정보

let 회원정보 = [{
    아이디 : 'jjang',
    패스워드 : '5dbfbded05f34de754e8f265448be17934580556b488c0461fd12d211a87aaa5',
    성별 : '남',
    휴대폰번호 : '010-5004-0000',
    이메일 : 'hojun1@gmail.com',
    가입연도 : '2020-12-02',
    주접속위치 : '125.242.161.149'
}, {
    아이디 : 'jjang2',
    패스워드 : '5dbfbded05f34de754e8f265448be17934580556b488c0461fd12d211a87aaa5',
    성별 : '남',
    휴대폰번호 : '010-5004-0000',
    이메일 : 'hojun2@gmail.com',
    가입연도 : '2021-12-02',
    주접속위치 : '125.242.161.149'
}, {
    아이디 : 'jjang3',
    패스워드 : '5dbfbded05f34de754e8f265448be17934580556b488c0461fd12d211a87aaa5',
    성별 : '여',
    휴대폰번호 : '010-5004-0000',
    이메일 : 'hojun3@gmail.com',
    가입연도 : '2021-12-02',
    주접속위치 : '125.242.161.149'
}, {
    아이디 : 'jjang4',
    패스워드 : '5dbfbded05f34de754e8f265448be17934580556b488c0461fd12d211a87aaa5',
    성별 : '여',
    휴대폰번호 : '010-5004-0000',
    이메일 : 'hojun4@gmail.com',
    가입연도 : '2020-12-02',
    주접속위치 : '125.242.161.149'
}];

1번. 남자인 사람
회원정보.filter(el => el.성별 === '남')

2번. 남자이면서 2021년도에 가입하신 분

  • 내답
    회원정보.filter(el => (el.성별 === '남')*(el.가입연도.slice(0,4) === '2021'))

    나도 모르게 엑셀에서 조건을 줄 때 썼던 '*'를 써버렸다.. 논리연산자'&&'를 사용했어야 했는데!

  • 정답
    회원정보.filter(el => el.성별 === "남" && el.가입연도.split("-")[0] === "2021")

3번. 아이디가 'jjang'인 사람(find 사용)

  • filter 사용했을 때: 회원정보.filter(el => el.아이디 === "jjang")
  • find 사용했을 때:회원정보.find(element => element.아이디 === "jjang");

find - mozilla 참고링크:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

filter는 다 둘러보면서 맞는지 확인한다.
find는 찾으면 멈춘다. 아이디는 겹치지 않으니(겹쳐도 태그가 있음), 효율이 좋다.


게시판 검색

let blogs = [{
        id : 1,
        title : 'title1',
        content : 'content1',
        section : '일상',
    }, {
        id : 2,
        title : 'title2',
        content : 'content2',
        section : '취미',
    }, {
        id : 3,
        title : 'title3',
        content : 'content3',
        section : '개발',
    }, {
        id : 4,
        title : 'title4',
        content : 'content4',
        section : '개발',
    }];
let s = '개발'
let data = s? blogs.filter(b => b.section === s): blogs;

Map&Set


Map

object가 순회가 안 된다. 이터러블하지 않다. 그래서 Map이 생겼다..
Map은 순회가 된다.

let m = new Map();

Map에 값을 넣기

m.set('하나', '1');
m.set(1, '하나');
m.set(true, 1);
m.set(false, 0);

Map의 값에 접근하기

console.log(m.get('하나'));
console.log(m.get(true));

Map의 값이 있는지 확인하기

console.log(m.has('하나'));

Map의 값을 제거하기

console.log(m.delete('하나'));
console.log(m.has('하나'));
console.log(m);

Map의 크기를 확인하기

console.log(m.size);

array의 데이터 타입이 object로 찍히는 것처럼
Mapobject로 찍힌다.

인덱스를 가지는 자료형을 맵핑하기



Set

교집합, 차집합, 합집합을 구하는게 가능하다.
Set은 순서가 없다. index로 호출 못한다.

let s = new Set('abcdeeeeeeeee');
console.log(s);
console.log(s.size);
-> Set(5) {'a', 'b', 'c', 'd', 'e'}
->  5


s.add('f')
-> Set(6) {'a', 'b', 'c', 'd', 'e', …}


s.delete('b')
-> true
s
-> Set(5) {'a', 'c', 'd', 'e', 'f'}
s.has('c')
-> true
s.size
-> 5
s.forEach(i=> console.log(i))
 -> a
 -> c
 -> d
 -> e 
 -> f


s.add('f');
-> Set(5) {'a', 'c', 'd', 'e', 'f'}
//중복이 안 된다.
let a = new Set('abc');
let b = new Set('cde');


a
-> Set(3) {'a', 'b', 'c'}
b
-> Set(3) {'c', 'd', 'e'}

교집합

[...a].filter(value => b.has(value))
-> ['c']

합집합

let union = new
Set([...a].concat(...b))
union
-> Set(5) {'a', 'b', 'c', 'd', 'e'}

new Set([...a, ...b]); 이것도 똑같이 나온다..

[...a] 전개표현식

 function add(...x){
     return x;
 }

add(1, 2, 3, 4, 5)
모던자바스크립트 예제(https://ko.javascript.info/rest-parameters-spread)

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];
Math.max(1, ...arr1, 2, ...arr2, 25); // 25

모던자바스크립트 예제(https://ko.javascript.info/rest-parameters-spread)

let arr = [3, 5, 1];
let arr2 = [8, 9, 15];

let merged = [0, ...arr, 2, ...arr2];




생각

아예 이렇게 어려워버리니까 더 집중하는 것 같다. 너무 어려우니까, 아주 조금이라도 이해하려면 집중을 하지 않으면 안 된다. 짧은 기간동안 배우는만큼 최대한 많이 배워가야지..! 그치만 어렵다 증말.


느낀점

잘한점

  • 집중 열심히 한 점.. 앞으로 더 어려우면 어려웠지 쉽지는 않을 것 같으니, 계속 열심히 하자!

고칠점

  • 수업 때 배운 내용을 복습하려고 보면 너무 막막해져서, 복습에 조금 소홀해진 것 같다. 어려운 만큼 더 열심히 복습하기!

계획

  • call by value 손으로 쓰면서 정리해보기.
  • 수업 전에 전날 정리한 내용 읽으면서 복습하기.
profile
2021.11~

0개의 댓글