[코딩노트] S1 Unit 10 - javascript koans 과제하기

나현·2022년 9월 7일
0

코딩노트

목록 보기
5/11
post-thumbnail

💡 이 포스트에는 Unit 10. javascript 핵심 개념과 주요 문법과 관련된 코딩과제를 하고 몰랐던 점이나 부족했던 점을 정리했다!
(누군가에게는 너무 쉬워 하품이 나올 수 있습니다.🥲)

과제 내용 정리하기

이번에는 코딩 연습문제가 아니라 주석으로 쓰여진 요구사항을 해결하며 스크립트 파일을 작성하고 테스트를 통과하는 과제를 했다.
koans는 불교(선종)에서 깨달음을 목적으로 하는 선문답을 의미한다.
깨달음을 얻기 위해 질문하고 답하는 것처럼 이제까지 배웠던 javascript의 개념을 직접 답하며 깨달아가는 과제이다.

이 과제를 해결하며 헷갈리거나 새로 알게된 것들을 정리해 보았다.

1. 숫자+문자, 숫자-문자, 숫자+boolean, ....

핵심 : console.log()를 활용해 결과를 확실히 확인해본다.
직접 확인해보면 기억에도 남고 좋다.

let a=1+'0'; //숫자랑 문자를 더하면 문자
let b=100-'1'; //숫자를 문자를 빼면 숫자계산을 한다.
let c=0+true; //숫자에 true를 더하면 true를 숫자1로 간주한다. 
let d=0+false; //숫자에 false를 더하면 false를 숫자0으로 간주한다.
let e='1'+true; //문자열에 불린값을 더하면 그대로 문자열을 반환한다.
let f='1'+false;

console.log(a); //'10'
console.log(b); //99
console.log(c); //1
console.log(d); //0
console.log(e); //'1true'
console.log(f); //'1false'

아래의 링크로 들어가보면 온갖 이상한(?) 값을 확인해볼 수 있다.
https://github.com/denysdovhan/wtfjs

2. 호이스팅, 함수 선언식, 함수 표현식

핵심 : 함수 선언식과 함수 표현식의 차이를 확실히 알고 호이스팅에 대해 알아본다.
호이스팅에 대해 알기 전에 함수 선언식과 함수 표현식에 대해 확실하게 알아야 한다.
함수 선언은 지정된 매개변수(parameter)를 갖는 함수를 정의하며 함수 이름이 필요하다.
함수 표현식은 표현식 내에서 함수를 정의하는 것으로 함수 이름을 생략할 수 있다.
함수 선언과 함수 표현식은 매우 유사한 생김새를 가졌으나 함수 이름의 생략 여부에 따라 큰 차이가 있다.

//함수 선언. 함수 이름은 myFunc1
fucntion myFunc1(){
  return '나는 함수 선언';
}
//함수 표현식. 함수 이름 생략됨(익명 함수)
let myFunc2=function(){
  return '나는 함수 표현식';
}

그리고 가장 큰 차이점은 호이스팅 여부이다.
호이스팅(hoisting)이란, 변수와 함수의 메모리 공간이 선언 전에 미리 할당되는 것을 뜻한다. 때문에 함수는 코드를 실행하기 전 함수 선언에 대한 메모리부터 할당하기에 함수 선언은 먼저 저장된다.
따라서 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있다.
반면 함수 표현식은 호이스팅 되지 않는다.

myFunc1(10); //10
myFunc2(20); //Uncaught ReferenceError
function myFunc1(value){
	return `함수 선언, 값: ${value}`;
}
let myFunc2=function(value){
	return `함수 표현식, 값: ${value}`;
}

참고:
javascript MDN - 함수 선언
javascript MDN - 함수 표현식
javascript MDN - 호이스팅

3. 기본값 매개변수(default parameter)

핵심 : 아무런 인자를 받지 못했을 때 매개변수도 기본값을 설정할 수 있다.
함수가 실행될 때 매개변수를 받아야 하지만 인자 값이 없거나 undefined가 전달될 경우, 매개변수에 설정된 기본값을 부여할 수 있다.
만약 인자를 재대로 전달했을 경우 전달된 인자를 우선 매개변수에 할당한다.

function myFunc(name='John Doe'){ //기본값은 'John Doe'
	return name;
}
myFunc();//'John Doe' -> 전달인자가 없어서 기본값 출력
myFunc('Jane Doe');//'Jane Doe' -> 전달인자 출력

참고: javascript MDN - 기본값 매개변수

4. 화살표 함수의 특징

핵심 : 화살표 함수 자체를 이해하기보다 주요 특징을 알아본다.

  • function키워드 없이 함수 표현식으로 사용한다.
  • 함수 중괄호 부분의 중괄호를 생략하고 한줄로 작성할 수 있다.
  • 중괄호를 소괄호로 대체할 수 있다.
  • 리턴문의 'return'부분을 생략할 수 있다.
  • 매개변수가 하나라면 매개변수의 소괄호를 생략할 수 있다.
  • 화살표 함수는 this가 없다.
// function 키워드를 생략하고 화살표 => 를 붙입니다
const add = (x, y) => {
  return x + y
}
expect(add(10, 20)).to.eql(30)

// 리턴을 생략할 수 있습니다
const subtract = (x, y) => x - y
expect(subtract(10, 20)).to.eql(-10)

// 필요에 따라 소괄호를 붙일 수도 있습니다
const multiply = (x, y) => (x * y)
expect(multiply(10, 20)).to.eql(200)

// 파라미터가 하나일 경우 소괄호 생략이 가능합니다
const divideBy10 = x => x / 10
expect(divideBy10(100)).to.eql(10)

5. 배열 메서드가 리턴하는 값

저번에 정리하긴 했으나 (포스트 -- 참고) 매번 헷갈리므로 다시 정리해보았다.

  • arr.shift(), arr.pop()
    -> 제거된 값
  • arr.unshift(추가할 값), arr.push(추가할 값)
    -> 변경된 후의 arr.length;
  • arr1.concat(arr2)
    -> arr1과 arr2를 합친 배열을 리턴한다.
  • arr.slice()
    -> slice()를 적용한 결과를 배열로 리턴한다.
  • arr.join();
    -> join한 결과를 리턴한다.
  • arr.splice()
    ->
    값을 추가만 할 경우 빈 배열을 리턴하고
    변경하면 변경한 값, 삭제하면 삭제한 값만 배열에 담아 리턴한다.

6. slice의 활용

핵심 : 배열.slice(strat, end)는 배열의 start를 포함하여 end를 미포함하여 end이전까지 배열로 리턴한다.
기본 원리를 알고 있다면 나머지는 이해하기 어렵지 않다.
그러나 여러 용도로 활용하면 헷갈리므로 한번에 정리해보았다.
임의의 배열 arr=[1,2,3,4]이 있다고 가정하자.

  • 기본 원리: arr.slice(strat, end);
    -> start를 포함하여 end이전까지(end 미포함) 배열로 리턴한다.
  • arr.slice(start);
    -> 시작index부터 마지막까지 가져온다.(마지막 포함)
  • index값이 문자열의 길이를 초과하면 마지막 index로 간주한다.
  • start >=end인 경우:
    빈 값이 출력된다.
  • start나 end가 음수인 경우:
    slice는 전체길이에 음수값을 더해 출력한다.
    쉽게 말해 뒤에서부터 센다.
    ex1. arr.slice(0,-1); //[1,2,3]
    -1은 뒤에서 첫번째. 0부터 뒤에서 한 개를 미포함하여 그 전까지 가져온다.
    ex2. arr.slice(-2,-1); //[3]
    뒤에서 두번째를 포함하여 뒤에서 첫번째를 미포함하여 그 전까지 가져온다.

7. 전달인자와 매개변수

핵심 : 전달인자>매개변수면 전달인자 순서대로 매개변수에 적용이 되고, 전달인자<매개변수면 매개변수에 자동으로 undefined가 할당이 된다.
핵심 : 매개변수가 전달인자를 받아 할당할 때 참조자료형은 주소를 복사한다.(즉 매개변수로 값을 바꾸면 원본도 바뀐다.)

8. this의 개념

this는 현재 요소가 속한 객체를 나타낸다.
객체 내에서 this를 사용하면 이 때의 this는 그 객체이다.
전역에서 생성한 객체의 this는 window 객체로 이는 생략 가능하다.
그리고 this는 그 메서드를 호출할 때의 시점을 기준으로 정해진다.
향후 this에 대해서는 좀 더 배울 예정이다.

참고: javascript MDN -this

9. 얕은 복사(shallow copy)와 깊은 복사(deep copy)

원시 자료형은 변수에 값 자체를 보관하며
참조 자료형은 변수에 그 값이 있는 주소를 보관한다.
때문에 원시 자료형을 복사하며 그 값 자체가 복사되지만
참조 자료형 변수를 복사하면 주소가 복사된다.
만약 복사한 새로운 변수의 값을 변경하면 원본(처음 주소가 담긴 변수)도 변경된다. 다른 것 같지만 같은 주소이기 때문이다.
이렇게 값 자체가 복사되는 것을 깊은 복사, 주소만 복사되는 것을 얕은 복사라고 한다.

그리고 만약 배열이나 객체를 복사할 때 배열과 객체를 복사한 것 같아도
배열, 객체 안의 원시자료형의 값은 복사되지만
배역, 객체 안의 또다른 참조자료형은 주소만 복사된다. 이것도 얕은 복사이다.
또한 전개 구문으로 배열, 객체를 복사하는 것도 얕은 복사이다.

let arr1=[1,2,3];
let arr2=arr1;
arr2.push(4);
console.log(arr1); //[1,2,3,4] 
//-> arr2에 주소가 복사되었기에 원본인 arr1도 바뀐다.

let arr3=['a','b','c',['d','e']];
let arr4=Array.from(arr3); //배열을 얕게 복사하는 메서드
arr4.push('f');
console.log(arr3); //['a','b','c',['d','e']] 
console.log(arr4); //['a','b','c',['d','e'], 'f'] 
//-> 원시자료형의 값은 복사되었기에 원본이 변경되지 않았다.

arr4[3].push('f');
console.log(arr3); //['a','b','c',['d','e','f']] 
console.log(arr4); //['a','b','c',['d','e','f'], 'f']
// -> 복사된 배열 안의 배열 ['d', 'e']은 주소가 복사되어서 원본도 같이 변경된 것을 확인할 수 있다!

깊게 복사하기 위해서는 참고 링크의 내용을 확인하면 어느 정도 해결이 가능하나 나중에 좀 더 자세히 학습할 예정이다.

참고 링크: javascript MDN - Objcet.assign()-깊은 복사 주의점

10. arguments 객체

핵심 : 나머지 매개변수는 배열의 형태로 인자를 저장하지만, arguments는 객체 형태로 인자를 저장한다.
arguments는 브라우저의 콘솔로 확인해보면 인자 외에 여러 값을 객체로 저장한다.
그런데 Object.keys()를 사용해 키 값을 배열로 확인해보면
인자의 갯수만큼만 키를 반환하고,
Object.values()를 사용해 키 값을 확인해보면 인자만 있다.

function checkRest(...args){
  return args
}
function checkArgsObj(){
  return arguments
}
let resultRest=checkRest(1,2,3); //[1,2,3]
let resultArgsObj=checkArgsObj(1,2,3); 
//[1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(typeof resultRest); //'object'
console.log(typeof resultArgsObj); //'object'
console.log(Array.isArray(resultRest)); //true
console.log(Array.isArray(resultArgsObj)); //false

11. 구조 분해 할당

핵심 : 구조 분해 할당은 이름 그대로 구조를 분해하여 할당하는 것을 의미한다.
만약 배열이나 객체의 값 하나하나를 변수로 할당해야 할 때 여러 줄로 일일이 작성하면 비효율적일 수 있다.
이를 효율적으로 처리할 때 구조 분해 할당을 사용하면 편리해진다.

//배열 값을 각 변수에 한 번에 할당할 수 있다.
let pizza=['cheese', 'pepperoni', 'shrimp', 'combination'];
let [menu1, menu2, menu3, menu4]=pizza;
console.log(menu1); //'cheese'
console.log(menu2); //'pepperoni'
console.log(menu3); //'shrimp'
console.log(menu4); //'combination'

//인자를 객체로,매개변수에 키를 입력하면 자동으로 분해되어 할당된다.
let person={name:'코난',job:'탐정'};
function introduce({name,job}){
  return `내 이름은 ${name}, ${job}이죠.`;
}
introduce(person);//'내 이름은 코난, 탐정이죠.'

//전개 문법, 나머지 매개변수와도 함께 사용할 수 있다.
//다만, 순서대로 할당된다.
let fruitsBox={
  apple:1,
  banana:5,
  shineMusket:1,
  orange:1
}
let appleBoyCart={
  ...fruitsBox,
  apple:10, //apple:10 재할당
  banana:1 //banana:1 재할당
}
let bananaGirlCart={
  apple:4,
  ...fruitsBox, //apple:1 재할당
  banana:10 //banana:10 재할당
}
console.log(appleBoyCart); 
//{apple: 10, banana: 1, shineMusket: 1, orange: 1}
console.log(bananaGirlCart); 
//{apple: 1, banana: 10, shineMusket: 1, orange: 1}

추가로 알게된 메서드

  • '문자열'.repeat(count)
    문자열을 count만큼 반복하여 한 문자열로 만든다.
    count는 정수이며 정수가 아니면 자동으로 정수로 변환된다.
  • Object.values(obj)
    객체 obj의 값만 배열로 가져온다.
    cf. Object.keys(obj)는 객체 obj의 키만 배열로 가져온다.
  • new Date()
    현재 날짜를 다음과 같은 형태로 반환한다.
    Thu Sep 08 2022 20:25:40 GMT+0900 (한국 표준시)
  • getFullYear()
    new Date()로 생성되는 날짜의 년도를 가져온다.
    참고: javascript MDN - Date.prototype.getFullYear()
  • Array.from()
    배열을 얕게 복사하여 새로운 배열로 만든다.
    참고: javascript MDN - Array.from()
  • Object.assign(복사할 대상이 되는 객체, 복사할 객체)
    복사할 대상이 되는 객체에 복사할 객체를 붙여넣어 하나의 객체로 만든다.
    속성이 겹칠 경우 복사할 객체의 값으로 갱신되며
    얕은 복사이다.
    참고: javascript MDN - Object.assign()

노트 정리 후 느낀점

이제까지 배운 내용 + 추가로 알게 된 내용을 한 번에 정리해보는 시간이었다.
페어와 함께 차근차근 문제를 풀어보면서 모르는 내용을 그때그때 정리했고
배우지 않았던 내용은 직접 검색하며 찾아보았다.
확실히 한 번에 정리하다보니 알고있던 것도 헷갈려서 다시 공부할 수 있었고,
모르는 내용은 다음에 유용하게 쓸 수 있게 잠깐 정리할 수 있었다.
몰랐던 내용은 이제 확실히 잘 안다고 할 수는 없지만, 전부 다음 학습에서 배운다고 하니 그때가서 좀 더 이해되지 않을까?

  • 이번의 부족한 점
    • 이미 알고있었던 내용들도 복습하니 헷갈리는 경우가 있었다.
    • 알고 있을거라 생각하고 그냥 풀고 넘어가면 틀린다.
    • 터미널 사용법이 아직은 미숙하다.

오늘은 위의 부족한 점을 보완하기 위해 아래와 같이 공부했다!

  • 부족한 점 보완하기
    • 정리만 할 게 아니라 문제를 풀어보거나 이미 풀었던 문제들도 다시 보는 습관이 필요하다.
    • 확실하지 않다면, 테스트를 통과하지 못했다면 반드시 브라우저 콘솔에 직접 확인해보자!
    • 터미널 사용과 npm 사용, package.json 설치에 익숙해지자. 특히 에러가 나면 꼼꼼하게 읽어보자.

과제는 다행히 제시간에 제출했지만
공부량은 많아서 오늘도 이렇게 나머지 공부를 한다.
피곤하지만 괜찮다! 확실히 공부하는 좋은 기회였다.
오늘도 이렇게 돌다리를 두드리며 넘어가고
머릿속 지식전구에 불을 하나 켜본다.

🤓

profile
프론트엔드 개발자 NH입니다. 시리즈로 보시면 더 쉽게 여러 글들을 볼 수 있습니다!

0개의 댓글