📌 test 작성 방법
test를 위해서 koans은 두가지 모듈을 사용하고 있는데, 바로 mocha와 chai이다.
이때 테스트하는 값과 기대값을 비교하기 위해 expect() 함수를 사용하게 된다.
expect(true).to.be.true // 통과
expect(테스트하는 값).기대하는 조건
이런 형태로 사용하게 되는데 여기서 기대하는 조건에 해당하는 것을 matcher함수라고 부른다.
chai는 matcher를 다양한 language chains과 assertions으로 만드는데,[여기](http:// https://www.chaijs.com/api/bdd/#method\_not)에%EC%97%90) 다양한 체인과 assertion들이 소개되어 있다.
koans에서는 to.be
, to.
체인만 사용했다.
to.be
에는 boolean으로 판별하는 true
, false
가 오기도 하고
to.
에는 equal()
이 오기도 한다.equal
은 두 값 A와 B가 타입까지 같은지 엄격하게 검사한다. (strick equality, ===)
반대로 비교연산자 ==
는 두 값의 일치 여부를 느슨하게 검사한다.(loose equality)
예를 들어, 연산자가 들어가는 test에서는
expect(1+1 == 2 ).to.be.true; // true
expect(1+1 == '2').to.be.true; // true
문자열과 숫자를 같다고 하고 있다. 이 외에도 falsy한 값을 false라고 하거나
비어있는 배열과 비어있는 문자열을 같다고 하기도 한다... 역시 ===
만 사용하는 게 훨씬 마음 편하다.
📌 다양한 메소드
koans에서 출몰한 다양한 메소드를 소개해보겠다.
- Object.toString() : object를 문자열로 변환함. 기본적으로 객체가 문자열로 참조될 것 같을 때 자동으로 호출됨. 🔗
- Object.assign(target, source) : target에 iterable한 source를 복사한 후 target을 반환한다. (얕은 복사) 🔗
- Array.from(arraylike, [mapFn [, thisArg] ]) : iterable한 arraylike(유사 객체, 반복가능 배열)를 복사하여 mapFn함수를 거친 새로운 array를 만듦. mapFn부터는 생략 가능함. thisArg는 mapFn 실행 시의 this 값이다. 🔗
- array.slice(start , end) : start 포함된 end전까지의 새 배열을 반환한다.
- start가 end보다 크가니 같으면 빈 배열을 반환한다.
- end가 array.length보다 크면 끝까지 복사한다.(slice는 쓸 때마다 헷갈리는 것 같다😥)
console.log(arr.slice(5, 1)); //[]
- String.repeat(n) : 문자열 주어진 횟수만큼 반복 🔗
📌 default parameter (기본값 매개변수)
: 값이 없거나 undefined인 변수가 들어와도 기본값으로 함수가 처리된다.🔗
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5)); // 5
console.log(multiply()); // 1
📌 스코프와 클로저
스코프 : 변수 접근 규칙 🔗
- 안쪽에서 바깥쪽 접근 가능, 바깥에서 안쪽 불가능
- 스코프 중첩 가능
전역 스코프 (global scope) : 가장 바깥쪽 스코프
지역 스코프 (local scope) : 안쪽 스코프
함수 스코프 : 함수로 만들어진 스코프 (함수 선언식, 함수 표현식)
블록 스코프 : 블록으로 만들어진 스코프 (화살표 함수 등)
렉시컬 스코프 : 스코프가 생길 때의 어휘적 환경
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // ?
bar(); // ?
함수가 호출될 때가 아니라 함수가 선언될 때 상위 스코프가 결정된다.
bar()는 선언 전에 호출되고 있지만 호이스팅으로 인해 최상위 스코프에 선언만 옮겨졌다.
따라서 선언 전에 호출을 해도 작동이 가능하다.
또한 bar() 선언에서의 x는 전역 변수인 x = 1 가 사용되므로 bar는 무조건 1을 반환하게 된다.
따라서 둘 다 1을 반환한다.
var : 함수 스코프만 유효, 화살표 함수 블록 스코프 제외한 블록 스코프 무시
let, const : 함수, 블록 스코프 유효
클로저 : 함수와 그 함수의 렉시컬 환경(스코프) 의 조합 🔗
함수 안에 함수가 있고 그 바깥쪽에서 정의된 것을 안쪽에서 사용할 때,
바깥쪽 함수가 끝나도 안쪽 함수에선 그 변수가 남아있다.
클로저 은닉화 : 클로저를 이용해 바깥에서는 클로저 내의 변수에 접근하지 못하게 할 수 있다.
📌 참조자료형과 스코프
참조자료형인 전역변수를 다른 변수에 할당하면 reference가 할당된 것이다.
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');
헷갈렸던 점 : reArr라는 새로운 변수가 선언된 게 아닌가?
=> 선언됐더라도 arr의 reference를 할당했기 때문에 arr[1]이 바뀜.
📌 object.length
:object는 length 속성이 없다.
그러면 object.length는 뭐가 나올까?
바로 undefined이다.
Object.keys(obj)를 사용하면 키 부분의 새 array를 얻을 수 있고, length를 구할 수 있다. 🔗
📌 this
: 호출당시 자신의 렉시컬 스코프에 해당하는 객체부분을 가리킴
- 객체에서 본인의 키 값을 참조하고 싶을 때
내가 생각하기로는 각각의 키 값 자체가 같은 단계에서 다른 지역변수를 가지고 있기 때문에 다른 키에서는 참조가 안되는 것 같다. 아예 하위 스코프인 megalomaniac객체에서 그 키를 불러내는 것은 가능한 거로 보면...
📌 ...rest paremeter
: 함수의 전달인자로 사용되며 정해지지 않은 인자를 받을 수 있다. 🔗
- 여러 개의 전달인자를 넣으면 하나의 배열로 반환된다.
function getAllParamsByRestParameter(...args) {
return args;
}
const restParams = getAllParamsByRestParameter('first', 'second', 'third');
expect(restParams).to.deep.equal(['first', 'second', 'third']);
- rest parameter를 함수 전달인자로 사용하고 실제 함수 작동할 때 전달인자에 ...args 넣지 않으면 빈 배열 반환
function getAllParams(required1, required2, ...args) {
return [required1, required2, args];
}
expect(getAllParams(123)).to.deep.equal([123, undefined, []]);
rest parameter랑 spread랑 조금 헷갈리는데 이 부분은 rest는 함수에서 나머지 인자를 받는 역할,
spread는 아무데나 사용될 수 있으면서 펼치는 것! 으로 생각하면 될 것 같다.
spread로 처음에 정의해둔 변수를 함수 내로 가져와서 사용할 수도 있다.
📌 구조 분배 할당 구문
: 배열이나 객체의 속성을 해체하여 그 값을 개별 변수로 사용할 수 있게 만드는 구문
구문 사용 시 선언 필수 🔗
const array = ['code', 'states', 'im', 'course']
const [first, second] = array
expect(first).to.eql('code') //통과
const student = { name: '박해커', major: '물리학과' }
const { name } = student
expect(name).to.eql('박해커') //통과
const student = { name: '최초보', major: '물리학과' }
const { name, ...args } = student
expect(name).to.eql('최초보')
expect(args).to.eql({major: '물리학과'})
})
마지막 코드블럭에서는 rest parameter를 함께 사용했다.
여기서 rest parameter는 object를 반환했다.
📌 객체 단축 문법 (shorthand)
const name = '김코딩'
const age = 28
const person = {
name,
age,
level: 'Junior',
}
expect(person).to.eql({
name: '김코딩',
age: 28,
level: 'Junior',
})
객체 내부에 전역변수를 그냥 써도 키 부분은 변수, 키 값 부분은 변수에 할당된 수로 자동 변환된다.
> (객체란 내부에 변수블럭이 있는 것처럼 작동하는 것 같다...)
📌 팩토리 함수
: 함수가 객체를 반환하는 것
1. 기본적인 팩토리 함수
function createJelly() {
return {
type: 'jelly',
colour: 'red'
scoops: 3
};
}
2. 파라미터를 받는 팩토리 함수 (기본 값 매개변수를 사용)
function createIceCream(flavour='Vanilla') {
return {
type: 'icecream',
scoops: 3,
flavour
}
}
3. 팩토리 함수끼리 조합
function createDessert() {
return {
type: 'dessert',
bowl: [
createJelly(),
createIceCream()
]
};
}
위 두 팩토리함수를 조합하여 createDessert()라는 더 복잡한 팩토리 함수를 생성했다.
이외의 팩토리 함수는 아직 이해하기 어려워서 링크만 첨부! 🔗
📌 클로저 유즈 케이스
'Codestates SEB FE 42기 > 정리노트' 카테고리의 다른 글
S1 unit11 | DOM으로 javascript에서 html요소 편집하기 (0) | 2022.11.14 |
---|---|
S1 unit10 | 원시 자료형과 참조 자료형 (0) | 2022.11.13 |
S1 unit8 회고 | node.js(nvm, npm) & git (0) | 2022.11.08 |
S1 unit8 회고 | Linux CLI & 패키지 (0) | 2022.11.08 |
[SEB FE] Section1 unit6 회고 | html 레이아웃과 css flexbox (0) | 2022.11.08 |