복습 (스압)

JS2L·2023년 1월 6일
0

expect 학습

작성한 함수가 주어진 입력값에 대해서 리턴하는 값이 기대하는 값과 같은지를 비교할 때 expect 함수를 사용함.

expect의 사용법

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

expect(isEven(3)).to.be.true => 'isEven(3)'의 결과값은 참(true)이어야 한다'

expect(1 + 2).to.equal(3) => 'sum(1, 2)의 결과값은 3과 같아야(equal) 한다'



'기대하는조건'에 해당하는 함수를 matcher라고 합니다.

'참인 것이어야 한다' => to.be.true ex) it("테스트하는 값(expect의 전달인자)이 true인지의 여부를 검사합니다.", function () {

                                                    expect(true).to.be.true;

                                                });



'3과 같아야 한다' => to.equal(3) ex) it("Matcher .equal 의 사용법을 학습합니다.", function () {

                                                  let expectedValue = 2; // TODO

                                                  expect(1 + 1).to.equal(expectedValue);

                                                });

비교연산자 '=='는 두 값의 일치 여부를 느슨하게 검사(loose equality)합니다.

느슨하게 검사한다는 의미는 let actualValue = 1 + 1;

                               let expectedValue = 2;

                               expect(actualValue == expectedValue).to.be.true; 일 때

문자열 let expectedValue = 2; 를 대신해 let expectedValue = "2"; 를 넣어도 테스트에 통과 할 수 있다.

'=='의 실행 중 타입 변환(type coercion)이 일어나기 때문입니다.

비교연산자 '==='는 두 값의 일치 여부를 엄격하게 검사(strict equality)한다.

위의 느슨한 비교연산자와 같이 string 타입의 "2"를 적게되면 테스트에 통과하지 못한다.

https://github.com/denysdovhan/wtfjs -> 자바스크립트의 별난 부분들을 따로 모아둔 저장소

'const'로 선언된 변수에는 재할당(reassignment)이 금지됩니다.

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

'const'로 선언된 객체의 경우, 속성을 추가하거나 삭제할 수 있습니다.

scope는 변수의 값(변수에 담긴 값)을 찾을 때 확인하는 곳을 말합니다

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

lexical scope

it("lexical scope에 대해서 확인합니다.", function () {

let message = "Outer";

function getMessage() {

  return message;

}

function shadowGlobal() {

  let message = "Inner";

  return message;

}

function shadowGlobal2(message) {

  return message;

}

function shadowParameter(message) {

  message = "Do not use parameters like this!";

  return message;

}

expect(getMessage()).to.equal("Outer");

expect(shadowGlobal()).to.equal("Inner");

expect(shadowGlobal2("Parameter")).to.equal("Parameter");

expect(shadowParameter("Parameter")).to.equal(

  "Do not use parameters like this!"

);

expect(message).to.equal("Outer");

});

default parameter

it("default parameter에 대해 확인합니다.", function () {

function defaultParameter(num = 5) {

  return num;

}

expect(defaultParameter()).to.equal(5);

expect(defaultParameter(10)).to.equal(10);

function pushNum(num, arr = []) {

  arr.push(num);

  return arr;

}

expect(pushNum(10)).to.deep.equal([10]);

expect(pushNum(20)).to.deep.equal([20]);

expect(pushNum(4, [1, 2, 3])).to.deep.equal([1, 2, 3, 4]);

});

클로저

클로저는 함수와 함수가 선언된 어휘적 환경의 조합을 말한다.

이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.

여기서의 키워드는 "함수가 선언"된 "어휘적(lexical) 환경"입니다. 

특이하게도 자바스크립트는 함수가 호출되는 환경와 별개로, 기존에 선언되어 있던 환경 - 어휘적 환경 - 을 기준으로 변수를 조회하려고 합니다.

유어클레스 영상에서 언급되는 "외부함수의 변수에 접근할 수 있는 내부함수"를 클로져 함수로 부르는 이유도 그렇습니다.

클로저는 내부(inner) 함수가 외부(outer) 함수의 지역 변수에 접근할 수 있습니다.

함수 표현식 사용법

function 키워드를 생략하고 화살표 => 를 붙입니다.

ex) const add = (x, y) => {

  return x + y;

};

expect(add(10, 20)).to.eql(30);

리턴을 생략할 수 있습니다.

ex) const subtract = (x, y) => x - y;

  expect(subtract(10, 20)).to.eql(-10);

필요에 따라 소괄호를 붙일 수도 있습니다

ex) const multiply = (x, y) => (x * y);

expect(multiply(10, 20)).to.eql(200);

파라미터가 하나일 경우 소괄호 생략이 가능합니다

ex) const divideBy10 = (x) => x / 10;

expect(divideBy10(100)).to.eql(10);

화살표 함수 사용 클로저 예시

it("화살표 함수를 이용해 클로저를 표현합니다", function () {

const adder = (x) => {

  return (y) => {

    return x + y;

  };

};

expect(adder(50)(10)).to.eql(60);

const subtractor = (x) => (y) => {

  return x - y;

};

expect(subtractor(50)(10)).to.eql(40);

const htmlMaker = (tag) => (textContent) =>

  `<${tag}>${textContent}</${tag}>`;

expect(htmlMaker("div")("code states")).to.eql("<div>code states</div>");

const liMaker = htmlMaker("li");

expect(liMaker("1st item")).to.eql("<li>1st item</li>");

expect(liMaker("2nd item")).to.eql("<li>2nd item</li>");

});

primitive data type과 reference data type

name.toUpperCase() = 글자를 대문자로 변환 시킴 ex) let = name ='codestates' 일때 name.toUpperCase() === "CODESTATES"

원시 자료형을 변수에 할당할 경우, 값 자체의 복사가 일어납니다.

ex) let overTwenty = true;

let allowedToDrink = overTwenty; <--- allowedToDrink에 overTwenty 값이 복사됨.

overTwenty = false; <--- overTwenty 값이 false로 바뀜.(하지만 allowedToDrink의 값은 그대로 true인 상태)

expect(overTwenty).to.equal(false);

expect(allowedToDrink).to.equal(true);

원시 자료형 또는 원시 자료형의 데이터를 함수의 전달인자로 전달할 경우, 값 자체의 복사가 일어납니다.

ex) let currentYear = 2020;

 function afterTenYears(year) {

   year = year + 10;

 }

 afterTenYears(currentYear);

 expect(currentYear).to.equal(2020);

 function afterTenYears2(currentYear) {

   currentYear = currentYear + 10;

   return currentYear;

 }

 let after10 = afterTenYears2(currentYear);

 expect(currentYear).to.equal(2020); <--- afterYear에 묶이지 않기 때문에 전역 스코프인 2020을 가져오게됨

 expect(after10).to.equal(2030);

참조 자료형의 데이터는 동적(dynamic)으로 변합니다.

ex) const arr = [1, 2, 3];

expect(arr.length).to.equal(3);

arr.push(4, 5, 6);

expect(arr.length).to.equal(6);

arr.pop();

expect(arr.length).to.equal(5);

const obj = {};

expect(Object.keys(obj).length).to.equal(0);

obj["name"] = "codestates";

obj.quality = "best";

obj.product = [

  "sw engineering",

  "product manager",

  "growth marketing",

  "data science",

];

expect(Object.keys(obj).length).to.equal(3); <--- product에 여러가지 값이 있어도 주소는 하나라 1개로 셈

delete obj.name;

expect(Object.keys(obj).length).to.equal(2);

});

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

ex) const overTwenty = ["hongsik", "minchul", "hoyong"];

let allowedToDrink = overTwenty;

overTwenty.push("san"); // overTwenty = ["hongsik", "minchul", "hoyong", "san"]

expect(allowedToDrink).to.deep.equal([

  "hongsik",

  "minchul",

  "hoyong",

  "san",

]);

overTwenty[1] = "chanyoung"; // overTwenty = ["hongsik", "chanyoung", "hoyong", "san"]

expect(allowedToDrink[1]).to.deep.equal("chanyoung");

Array

Array.slice()구문 중 name.slice(0) <--- 코드 전체를 복사함. (자주 사용됨)

Array를 함수의 전달인자로 전달할 경우, reference가 전달됩니다.

ex) const arr = ["zero", "one", "two", "three", "four", "five"];

 function passedByReference(refArr) {

   refArr[1] = "changed in function"; 

 }

  passedByReference(arr);

  expect(arr[1]).to.equal("changed in function"); <--- "changed in function" 전달

 const copiedArr = arr.slice();

 copiedArr[3] = "changed in copiedArr";

 expect(arr[3]).to.equal("three");            <--- 이 경우 "three"를 전달

shift 와 unshift : shift는 배열의 가장 앞의 값을 제거, unshift는 배열의 가장 앞자리에 값 추가

Object

this. 는 메쏘드를 호출하는 시점에 결정됨

ex)it("'this'는 method를 호출하는 시점에 결정됩니다.", function () {

const currentYear = new Date().getFullYear();

const megalomaniac = {

  mastermind: "James Wood",

  henchman: "Adam West",

  birthYear: 1970,

  calculateAge: function (currentYear) {

    return currentYear - this.birthYear;

  },

  changeBirthYear: function (newYear) {

    this.birthYear = newYear;

  },

};

expect(currentYear).to.equal(2023);

expect(megalomaniac.calculateAge(currentYear)).to.equal(53);  <--- 생일 1970년 기준 오늘인 2023년까지

megalomaniac.birthYear = 2000;

expect(megalomaniac.calculateAge(currentYear)).to.equal(23);

megalomaniac.changeBirthYear(2010);

expect(megalomaniac.calculateAge(currentYear)).to.equal(13); 

'Object.assign'을 통한 복사는 reference variable은 주소만 복사하기 때문입니다.

이와 관련하여 얕은 복사(shallow copy)와 깊은 복사(deep copy)에 대해서 학습하시기 바랍니다.

가이드가 될 만한 학습자료를 첨부합니다.

  https://scotch.io/bar-talk/copying-objects-in-javascript

  https://medium.com/watcha/깊은-복사와-얕은-복사에-대한-심도있는-이야기-2f7d797e008a

Spread syntax

빈 배열에 전개문법을 사용해도 아무것도 전달되지 않는다.

여러개의 배열을 이어붙일 수 있다.

ex) const arr1 = [0, 1, 2];

const arr2 = [3, 4, 5];

const concatenated = [arr1, arr2];

expect(concatenated).to.deep.equal([

  [0, 1, 2],

  [3, 4, 5],

]);                                   <-- 이 코드와 같은 동작을 수행함 : arr1.concat(arr2);

여러 개의 객체를 병합할 수 있습니다.

ex) const fullPre = {cohort: 7, duration: 4};

 const me = {time: "0156", status: "sleepy"};

 const merged = { ...fullPre, ...me };

Destructuring

rest/spread 문법을 배열 분해에 적용할 수 있습니다

ex) it("rest/spread 문법을 배열 분해에 적용할 수 있습니다", () => {

const array = ["code", "states", "im", "course"];

const [start, ...rest] = array;

expect(start).to.eql("code");

expect(rest).to.eql(["states", "im", "course"]);

객체의 단축, 객체의 분해 또한 가능하다.

profile
신입 개발자의 독고다이 개발일지

0개의 댓글