티스토리 뷰

🔍 koans????

= 불교에서 유래된 단어로, 결론을 내리기 전에 이게 왜 맞는지 깊게 고민한다는 의미를 가짐

 

(각 주제의 문제를 해결하면서 알게 된 부분을 위주로 적어보겠다!)


► 01_Introduction

첫 번째 주제에서는 '기대하는 값'과 '결과로 나온 값'이 같은지 알아보는 expect함수를 사용했다.

expect(테스트하는값).기대하는조건

여기서 기대하는 조건에 들어가는 함수를 'matcher'라고 부른다.

expect(1+1).to.equal(2) // sum(1+1)의 결과값은 2와 같아야함
expect(true)to.be.true // 테스트하는 값이 true여야함

기대하는 값은 표현식 이거나 함수의 실제 실행 결과이다. 

(기대하는 조건에 들어가는 함수는 여러가지가 있지만 수업에서는 일부만 사용함)

 

to.be.true/fasle는 '비교한 결과'가 참인지 아닌지를 비교하기 때문에 직관적이지 않고 불편하다.

하지만 .equal은 두 값을 직접 비교하기 때문에 좀 더 직관적이다.

let expectedValue = 2;
expect(1 + 1).to.equal(expectedValue); // true

let actualValue = (1 + 1).toString();
expect(actualValue).to.equal(2); // false
expect(actualValue).to.equal('2'); // true

.equal은 두 값이 타입까지 엄격하게 같은지(===) 검사하기 때문에 타입까지 같아야 같은 값이라고 인식한다.

 


► 02_Types-part1

두 번째 주제에서는 타입에 대해 다루었다.

이 부분에서는 문제없이 지나갈 것이라고 생각했는데 예상과는 다른 문제가 있었다.

expect(123 - '1').to.equal(122)

처음에는 '문자열 결합 연산자(+)처럼 문자열과 숫자 타입의 데이터를 문자열 형태로 빼는 건가?'라는 생각으로 '23'이라고 예상했다.

그런데 통과가 되지 않아 구글링을 해보았더니 이럴수가..

다른 연산자(- * / %)는 숫자형이 문자형보다 우선시되기 때문에 더하기와 같은 문자형으로의 변환이 일어나지 않는다.

+에서는 문자형이 숫자형보다 우선시 되어 문자열이 합쳐진 형태로 나오는 거였다..

따라서 뒤에 오는 '1'은 숫자1로 형이 바뀌어 산술이 가능하게 된 것 이였다!!!

 

이 문제를 해결하고 나니 아래에 오는 문제도 이해가 갔다.

expect(1 + true).to.equal(2); 
expect('1' + true).to.equal('1true');

첫 번째 함수식에서 true는 1로 형변환이 일어나 1+2의 형태가 되었고, 두 번째 함수식에서는 문자열 'true'로 바뀌어 문자열이 합쳐진것이였다.

 


► 03_LetConst

세 번째 주제에서는 const로 선언한 함수를 다루었다.

const키워드로 선언한 변수에는 값의 재할당이 불가능하므로 이 점을 유의하여 문제를 해결했다.

그런데...

"'const'로 선언된 배열의 경우 새로운 요소를 추가하거나 삭제할 수 있습니다."
"'const'로 선언된 객체의 경우, 속성을 추가하거나 삭제할 수 있습니다."

네???

나는 뭘 배운건가..?하며 열심히 구글링을 하던 중..

const는 재할당이 금지된다. 이는 const 변수의 타입이 객체인 경우, 객체에 대한 참조를 변경하지 못한다는 것을 의미한다. 하지만 이때 
객체의 프로퍼티는 보호되지 않는다.
 다시 말하자면 재할당은 불가능하지만 할당된 객체의 내용(프로퍼티의 추가, 삭제, 프로퍼티 값의 변경)은 변경할 수 있다.

https://poiemaweb.com/es6-block-scope

 

let, const | PoiemaWeb

ES5까지 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이었다. var 키워드로 선언된 변수는 아래와 같은 특징이 있다. 이는 다른 언어와는 다른 특징으로 주의를 기울이지 않으면

poiemaweb.com

오옷..!!!!!

원시자료형일때와 참조자료형일때는 다르게 작동구나!

이러한 예외를 알고 나니 뒤에 나오는 문제도 풀 수 있었다.

 

+ 왜 let을 쓰는 대신 const를 추천할까?

객체를 재할당하는 경우는 생각보다 흔하지 않다. const 키워드를 사용하면 의도치 않은 재할당을 방지해 주기 때문에 보다 안전하다.

 


► 04_Scope

 

네 번째 주제에서는 스코프에 따른 변수의 값을 알아보는 문제와 클로저를 다뤘다.

먼저, 함수 호이스팅에 대해 알아보았다.

JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다.

https://developer.mozilla.org/ko/docs/Glossary/Hoisting

 

호이스팅 - MDN Web Docs 용어 사전: 웹 용어 정의 | MDN

JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다. var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다

developer.mozilla.org

설명만으로는 이해가 잘 가지 않아 예제를 살펴보았다.

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

catName("호랑이");

/*
결과: "제 고양이의 이름은 호랑이입니다"
*/
catName("클로이");

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

/*
결과: "제 고양이의 이름은 클로이입니다"
*/

두 코드의 차이를 알아보자면 함수 호출의 위치가 함수 선언의 전과 후로 나뉘었다는 것이다.

평소 작성하던 코드는 앞에 있는 코드처럼 먼저 함수를 선언한 다음 호출하는 방식을 사용했다.

그런데 자바스크립트에서 호이스팅은 "변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는" 것으로 아래쪽에 있는 방식으로 작성을 해도 함수는 작동한다.

 

호이스팅에 대한 이해를 하고 나니 문제를 푸는게 수월해졌다.

 


► 05_ArrowFunction

다섯번째로는 화살표함수에 대해 알아보았다.

화살표 함수에 대해 잘 알지 못하므로 구글링을 통해 나름대로 개념을 정리해보았다.

 

📌 화살표 함수

더보기

함수 표현식보다 간결한 문법으로 함수를 만들 수 있는 방법

let func = (arg1, arg2, ...argN) => expression

위의 함수를 함수 표현식으로 바꾸어본다면

let func = function(arg1, arg2, ...argN) {
  return expression;
};

두 함수식은 같은 결과를 리턴한다.

const subtract = (x, y) => x - y
expect(subtract(10, 20)).to.eql(-10)

화살표 함수를 보면 매개변수 x, y를 받아 x-y의 결과를 리턴한다.

만약, 매개변수가 한개라면 소괄호를 생략할 수 있다. 

하지만 매개변수가 하나도 없을때는 소괄호를 생략하면 안된다.

 

또, 화살표 함수를 사용해 클로저를 표현할 수 있다.

const adder = x => {
  return y => {
    return x + y
  }
}
//위 화살표 함수를 축약하면
const adder = x => y => x + y // return을 생략할 수 있음
adder(1)(2) // 3

 

 


► 06_Types-part2

여섯 번째 주제에서는 원시 자료형과 참조 자료형에 대한 문제를 다루었다.

여기서 기억하고 가야될 부분은

📌 '원시 자료형'은 값 자체에 대한 변경이 불가능하고 변수에 할당 시 값 자체의 복사가 일어난다.
📌 '참조 자료형'은 변수에 할당 시 값이 담겨있는 heap의 주소가 변수에 담기게 되고 값의 변형이 가능하다.

이러한 특징을 기억하고 있다면 문제를 푸는데 있어서 큰 어려움은 없을것이다.

하지만 약간의 고민을 하게 된 부분이 있었는데,

const person = {
  son: {
    age: 9,
  },
};
const boy = person.son;
expect(person.son === { age: 9 }).to.equal(false);

이 문제를 풀 때 순간적으로 '프로퍼티의 형태'가 같다는 이유로 true를 입력할 뻔 했다.

하지만 이 두 값은 형태가 같을 뿐 담겨있는 주소는 다르기 때문에 같지않다.

 


► 07_Array

일곱 번째 주제에서는 배열에 대해 다루었다.

배열에 관한 부분은 수업에서 배웠기 때문에 큰 문제는 없었지만

배열을 잘라서 복사해오는 .slice()에 대한 문제를 풀 때 약간의 고민이 필요했다.

const arr = ['peanut', 'butter', 'and', 'jelly'];

배열 arr을 .slice()로 잘라 복사해 왔을때 결과가 어떻게 나오는지 살펴보자.

expect(arr.slice(2, 2)).to.deep.equal([]); // 2번째 인덱스부터 2번째 이전의 인덱스까지 출력
expect(arr.slice(3, 0)).to.deep.equal([]); // 3번째 인덱스부터 0번째 이전의 인덱스까지 출력
expect(arr.slice(5, 1)).to.deep.equal([]); // 5번째 인덱스부터 1번째 이전의 인덱스까지 출력

사실,, 이 부분에 대해서는 아직 완벽하게 이해하지 못했다..

(설명을 듣고 추가해야할 부분!)

 

 


► 08_Object

여덟 번째 주제로 객체에 대한 문제를 다루었다.

객체 또한 수업에서 다루었기 때문에 문제를 푸는데 큰 어려움은 없었지만, 이런 문제가..

expect(megalomaniac.henchwoman).to.equal('Harley'); // henchwoman
expect(megalomaniac.henchWoman).to.equal(undefined); // henchWoman

두 함수의 차이는.. w와 W...

코드 작성시 주의할 점을 이렇게 다시 상기시켜주는 문제라니... 정말 유익하다!

 

그렇게 한 차례의 고비를 넘기고 더 이상의 시련은 없을 줄 알았으나..

처음 보는 this키워드와, Date()생성자..

이 두 문제는 mdn의 설명을 보며 이해가 가능했다.

하지만 진짜 문제는 ..

const obj = {
  mastermind: 'Joker',
  henchwoman: 'Harley',
  relations: ['Anarky', 'Duela Dent', 'Lucy'],
  twins: {
    'Jared Leto': 'Suicide Squad',
    'Joaquin Phoenix': 'Joker',
    'Heath Ledger': 'The Dark Knight',
    'Jack Nicholson': 'Tim Burton Batman',
  },
};
const copiedObj = Object.assign({}, obj);

delete obj.twins['Jared Leto'];
expect('Jared Leto' in copiedObj.twins).to.equal(false); // 왜????

분명 객체의 불변성을 유지하기 위해 .assign()을 사용한다고 배웠는데 이게 무슨???

하지만 이내 발견했다.

마지막 테스트 코드의 결과가 예상과는 달랐을 수도 있습니다.
'Object.assign'을 통한 복사는 reference variable은 주소만 복사하기 때문입니다.
이와 관련하여 얕은 복사(shallow copy)와 깊은 복사(deep copy)에 대해서 학습하시기 바랍니다.

얕은 복사... 깊은 복사..?

원본 최상위 속성이 참조 없이 복사되고 값이 객체인 원본 속성이 존재하여 참조로 복사되는 경우 객체를 얕은 복사라고 합니다. 
소스 값이 개체에 대한 참조인 경우 대상 개체에 대한 참조 값만 복사합니다.

https://www.digitalocean.com/community/tutorials/copying-objects-in-javascript

 

Copying Objects in JavaScript | DigitalOcean

 

www.digitalocean.com

Object.assign()은 얕은 복사본만 만든다. 얕은 복사의 경우 원본 객체의 '열거 가능한 자체 속성'인 참조 값만 가져오는 것이다.

따라서 내부에 들어있는 객체(중첩된 객체)를 변경하면 같은 주소를 사용하고 있기 때문에 복사된 변수에도 영향을 주는 것이다.

 


► 09_SpreadSyntax

아홉 번째 문제.. 스프레드문법에 대한 문제를 다루었다.

스프레드 문법은 이전에 코플릿 문제를 풀다 구글링을 통해 알고 있었으므로 큰 문제 없이 해결해나갔다.

하지만 역시나..

arguments는 모든 함수의 실행 시 자동으로 생성되는 '객체'입니다.
arguments를 통해 '비슷하게' 함수의 전달인자들을 다룰 수 있습니다.

또 처음 보는 객체가..

우선 mdn에 나와있는 설명을 보고 문제를 해결했다.

더보기
arguments
➡︎
모든 함수 내에서 이용 가능한 지역 변수.
   
함수 내에서 모든 인수를 참조할 수 있으며, 호출할 때 제공한 인수 각각에 대한 항목을 갖고 항목의 인덱스는 0부터 시작

 


► 10_Destructuring

마지막 주제는 '구조 분해 할당'에 대한 문제를 다루었다.

'구조 분해 할당'이 뭐지?

객체나 배열을 변수로 '분해’할 수 있게 해주는 특별한 문법

설명만으로는 이해가 되지 않아 간단한 예제를 살펴보았다.

const array = ['code', 'states', 'im', 'course']
const [first, second] = array
// 구조 분해 할당을 이용해 
// first에는 array[0]
// second에는 array[1]을 할당
expect(first).to.eql('code') 
expect(second).to.eql('states')

예제를 보니 이해가 가는것 같기도..?

그런데 문제를 풀다보니 새로운 형태의 구조 분해 할당식이 나왔다.

const student = { name: '박해커', major: '물리학과' }
const { name } = student

위에랑 다른 형태를 보니 위에서는 배열을, 아래에서는 객체를 분해한 모습이였다.

그렇게 이해를 하고 나니 다른 문제도 해결할 수 있었다.

728x90

'코딩 > 코드스테이츠' 카테고리의 다른 글

[사용자 친화 웹] - UI / UX 개념과 관계성  (0) 2023.02.16
SECTION 1을 완주했다.  (0) 2023.01.11
[JavaScript] 원시 자료형과 참조 자료형  (0) 2023.01.02
[CSS] 기초(1)  (0) 2022.12.25
[HTML] 기초  (0) 2022.12.25