[Javascript] JavaScript Koans

Yuni·2022년 7월 13일
0

코드스테이츠

목록 보기
11/39
post-thumbnail

유닛 테스트하는 방법

테스트하는 값과 기대값을 비교하기 위해 expect 함수를 사용한다.
expect(테스트하는값).기대하는조건 / expect(1 + 2).to.equal(3)

기대하는조건에 해당하는 함수를 matcher라고 한다.
'3과 같아야 한다' => to.equal(3)

다양한 matcher 확인하기

타입

// 숫자와 숫자처럼 보이는 문자를 더할 경우 숫자가 문자 취급되어 더해진다.
1 + "1" === "11";

// 숫자와 숫자처럼 보이는 문자를 뺄 경우 문자가 숫자 취급되어 제해진다.
123 - "1" === 122;

// 숫자와 boolean 값을 더할 경우 boolean이 숫자 취급되어 더해진다(true는 1, fasle는 2)
1 + true === 2;

// 문자와 boolean이 더해질 경우 boolean이 문자로 취급되어 더해진다.
"1" + true === "1true";

let과 const

// const로 선언된 배열, 객체의 경우 재할당은 안되지만 새로운 요소를 추가하거나 삭제할 수는 있다.
const arr = [];
arr.push(42);
expect(arr[0]).to.equal(42);

스코프

console.log(typeof funcDeclared); // "function"

function funcDeclared() {
      return 'this is a function declaration';
}

🤔 funcDeclared가 선언되기 전인데 왜 undefined가 아닌 함수로 나올까?

호이스팅의 개념에 대해 알아보자!

📌 호이스팅
함수 안에 있는 선언들을 끌어올려서 함수 유효 범위(함수 블록 안)의 최상단에 선언하는 것을 말한다.
👉 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것

  • var 변수 선언과 함수선언문에서만 호이스팅이 일어난다(선언⭕ 할당❌)
  • let/const 변수 선언과 함수표현식에서는 호이스팅이 발생하지 않는다.

참고

원시자료형과 참조자료형

참조자료형을 변수에 할당할 경우 데이터의 주소가 저장된다.

const overTwenty = ['hongsik', 'minchul', 'hoyong'];
let allowedToDrink = overTwenty; // 배열의 주소 할당

// overTwenty에 요소를 추가해줬지만 overTwenty과 allowedToDrink는 같은 주소를 가지고 있다.
// 그 주소는 heap에 있는 배열을 바라보기 때문에 변경 사항이 동일하게 적용된다.
overTwenty.push('san');
expect(allowedToDrink).to.deep.equal(['hongsik', 'minchul', 'hoyong','san']);

💡 deep.equal

  • .deep.equal은 배열의 요소나 객체의 속성이 서로 같은지 확인하는 matcher이다.
  • equal만 사용할 경우 주소값이 같은지 확인하지만 deep.equal는 값이 같은지(동일한 형태인지..)만 확인한다.

배열

slice는 어떤 배열의 begin부터 end까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환한다.

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

// begin이 배열의 길이보다 큰 경우에는, 빈 배열을 반환한다.
arr.slice(100, 110) // []

// end 값이 배열의 길이보다 크다면 slice()는 배열의 끝까지 가져온다.
arr.slice(3, 100) // ['jelly']

arr.slice(3, 0) // [] 
arr.slice(2, 2) // []

배열을 함수의 인자로 전달할 경우 배열의 주소가 전달된다.

const arr = ['zero', 'one', 'two', 'three', 'four', 'five'];

function passedByReference(refArr) {
	refArr[1] = 'changed in function';
}

passedByReference(arr);
console.log(arr[1]); // "changed in function"

객체

Object.assign()

출처 객체들의 속성을 복사해 대상 객체에 붙여넣고 대상 객체를 반환한다.

Object.assign(target, ...sources)

  • target : 대상 객체. 출처 객체의 속성을 복사해 반영한 후 반환할 객체
  • sources : 출처 객체. 목표 객체에 반영하고자 하는 속성들을 갖고 있는 객체
  • 반환 값 : 목표 객체
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);
copiedObj.mastermind = 'James Wood';
console.log(obj.mastermind) // 'Joker'

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

🤔 obj의 twins에서 'Jared Leto'을 삭제한 건데 왜 copiedObj.twins에서도 사라졌을까?

Object.assing()이 중첩 구조(obj.twins)를 그대로 복사하지않고 중첩 구조의 주소값(twins 속성의 값인 객체의 주소)을 받아왔기 때문이다.

아래 그림과 같이 만약 c에 4번째 인덱스가 배열이라면 배열 자체를 가져오지 않고 heap에 할당된 배열의 주소를 가져온다. 그렇기 때문에 다른 곳에서 데이터를 변경하면 같이 변경된다.

깊은 복사와 얕은 복사 심화 내용

spread와 rest

// 빈 배열에 spread를 사용하면 아무것도 전달되지 않는다.
const spread = [];
const arr = [0, ...spread, 1]; 
console.log(arr); // [0, 1]

// rest를 사용해 파라미터를 넣어주면 배열의 형태로 들어간다.
// rest 파라미터는 항상 배열이기 때문에 값을 넣지 않으면 빈 배열이 된다
function getAllParamsByRestParameter(...args) {
	return args;
}

const restParams = getAllParamsByRestParameter('first', 'second', 'third');
expect(restParams).to.deep.equal(['first', 'second', 'third']);

// arguments는 모든 함수의 실행 시 자동으로 생성되는 객체다.
function getAllParamsByArgumentsObj() {
	return arguments;
}

const argumentsObj = getAllParamsByArgumentsObj('first', 'second', 'third');
expect(Object.keys(argumentsObj)).to.deep.equal(["0", "1", "2"]);
expect(Object.values(argumentsObj)).to.deep.equal(['first', 'second', 'third']);

Array.from()

유사 배열 객체나 반복 가능한 객체를 얕게 복사해 새로운 배열로 만든다.
console.log(Array.from('foo')); // Array ["f", "o", "o"]

const argsArr = Array.from(argumentsObj);

expect(Array.isArray(argsArr)).to.deep.equal(true);
expect(argsArr).to.deep.equal(['first', 'second', 'third']);

구조 분해 할당

// rest/spread 문법을 객체 분해에 적용할 수 있다.
const student = { name: '최초보', major: '물리학과' }
const { name, ...args } = student

expect(name).to.eql('최초보')
expect(args).to.eql({major:'물리학과'})

//============================================================

const student = { name: '최초보', major: '물리학과', lesson: '양자역학', grade: 'B+' }

function getSummary({ name, lesson: course, grade }) {
	return `${name}님은 ${grade}의 성적으로 ${course}을 수강했습니다`
}

expect(getSummary(student)).to.eql("최초보님은 B+의 성적으로 양자역학을 수강했습니다")
profile
배운 것을 기억하기 위해 기록합니다 😎

0개의 댓글