1/4 일일정리 Javascript Koans
페어와 함께 Javascript 파일을 10개 받아서 expect에 값을 대입하면서 문제를 풀었다.
약간 부족하거나 신기한 개념 위주로 정리해봤다.
1/3 ~ 1/4 진행
1. introduction
expect 함수를 사용하는법을 배웠다. 테스트 코드를 고치면 바로바로 정답을 확인할 수 있었다.
외부 라이브러리를 이용한 함수이다.
2. Type -part1
- 타입이 다른 두 값을 연산할 때 타입이 바뀌는 경우가 있다.(사실 꽤 많은듯 하다.)
1 + '1' // '11' String type 순서는 상관없음
123 - '1' // 122 Number type *, /, %등도 마찬가지로 Number type으로 변환
1 + true // 2 Number type true는 1 false는 0 으로 판단
true + '1' // 'true1' String type
이렇게 연산중에 예상치 못하게 타입이 바뀌는 경우를 암묵적 타입 변환이라고한다. 암묵적 타입 변환을 잘 이용하면 가독성 좋게 코드를 작성할 수 있다고 한다.
- 위와 같이 의도치 않게 타입이 변환되는 경우도 생기므로 느슨한 동치 연산자(==)는 쓰지 않는 것이 좋을 것 같다.
3. LetConst
- 원시값은 const로 선언하면 재할당이 불가능하고 값의 변경도 불가능하다. 하지만 참조값을 const로 선언하면 재할당은 불가능하지만, 객체나 배열 내 프로퍼티나 요소값은 변경할 수 있다.
4. Scope
- Scope가 약간 헷갈리는게 많은데 확실히 기억해 둘것은
⓵ 일단 지역(블록 내부)에서 선언된 변수는 지역 밖으로 나오지 못한다.
⓶ 값을 가지고 나오고 싶으면 다른 전역변수(혹은 상위지역변수)에 담아서 나오거나 함수 자체에 리턴하면된다.
- 함수선언문은 선언문 이전에 호출할 수 있고(호이스팅 되기 때문에),
함수 표현식은 할당문 이전에 호출하지 못한다.(호이스팅은 되지만 할당 되는 순간 함수가 된다.)
console.log( add(2,1)) ; // 3
console.log( subtract(2,1)); // Error : Cannot access 'subtract' before initialization
function add(x,y) {
return x + y;
}
const subtract = function (x,y) {
return x - y ;
}
- 클로저를 이용하면 함수종료후에도 지역변수에 접근할 수 있다.
5. Arrow function
MDN에 있는 기본 화살표 함수 문법
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 다음과 동일함: => { return expression; }
// 매개변수가 하나뿐인 경우 괄호는 선택사항:
(singleParam) => { statements }
singleParam => { statements }
// 매개변수가 없는 함수는 괄호가 필요:
() => { statements }
클로저와 화살표 함수를 이용한 HTML 태그 작성하기
const htmlMaker = (tag) => (textContent) =>
`<${tag}>${textContent}</${tag}>`;
htmlMaker("div")("code states")
// 실행결과
// "<div>code states</div>"
6. Type - part2
- 원시값은 변경 불가능한 값으로 값 자체는 변경할 수 없다.
let str = 'kim'
console.log(str.toUpperCase()); // KIM
console.log(str); // kim 값은 그대로이다.
문자열 덧붙이기의 경우 값자체를 바꾸는 것이 아니라 계속 재할당 해주는 것이다.
let str = 'abc';
str = str + 'd' ;
console.log(str); //'abcd'
str = str + 'e' ;
console.log(str); //'abcde'
// 값이 바뀌는 것 처럼 보이지만 재할당 하는 것이다.
- 구조분해할당을 사용하면 변수의 자리바꾸기가 가능하다.
let a = 5 ;
let b = 'kim' ;
[a, b] = [b, a] ;
console.log(a); // 'kim'
console.log(b); // 5
- 참조값 비교를 할 때는 주소를 비교한다.
let arr = [1, 2, 3]
let arr2 = [];
arr2 = arr ;
console.log(arr2 === arr); // true 같은 배열을 참조하고 있다.(주소가 동일하다.)
console.log(arr === [1,2,3]); // false 같은 배열 같지만 주소가 다르기 때문에 false이다.
- equal을 사용하면 객체나 배열의 주소값을 비교하고 deep.equal 을 사용하면 객체나 배열의 속성이나 요소를 하나하나 비교한다.
let arr = [1, 2, 3];
let arr2 = [1, 2, 3];
expect(arr).to.equal(arr2); // false
expect(arr).to.deep.equal(arr2); // true
7. Array
- 계속 까먹게 되는데 객체를 대괄호 접근법으로 접근할 때 키를 문자열로 만들어줘야 한다.
- pop매서드와 shift매서드는 제거한 요소를 리턴한다.
let arr = [1,2,3];
let result1 = arr.shift();
console.log(result1); // 1
let result2 = arr.pop();
console.log(result2); // 3
- unshift, shift, push, pop은 원본 배열을 바꾼다.
let arr = [1,2,3];
let arr2 = arr;
arr2.push(4);
arr2.shift();
arr2.unshift(1);
console.log(arr); // [1,2,3,4]
- slice 사용법. slice는 배열을 복사한다.
const arr = ["peanut", "butter", "and", "jelly"];
let result = arr.slice(0,2); // 0번부터 2번 전까지 짜른다.
console.log(result); // ['peanut', 'butter']
console.log(arr); // ["peanut", "butter", "and", "jelly"] 원본변화없음
let result2 = arr.slice(0); // 배열 그냥 복사
console.log(result2); // ["peanut", "butter", "and", "jelly"]
8. Object
- 객체는 length로 길이를 구할 수 없다. 길이를 알고 싶으면 Object.keys 매서드를 이용해 키를 배열로 만든 후 길이를 구한다.
let obj = {name : 'kim', age : 100};
console.log(obj.length); // undefined
let lgth = Object.keys(obj).length;
console.log(lgth); // 2
- in 연산자는 객체안에 프로퍼티가 있는지 확인하는 연산자다.
let obj = {name : 'kim', age : 100};
console.log('name' in obj); // true
console.log('height' in obj); // false
- this는 매서드를 호출하는 시점에서 결정된다. 일단은 이렇게만 알아두는게 좋을 것 같다.
let circle = {
radius : 5,
getArea : function(){
let area = Math.PI * this.radius * this.radius
return area
}
}
console.log(circle.getArea()); // 78.5398...
circle.radius = 10;
console.log(circle.getArea()); // 314.1592...
- 객체를 함수의 인자로 전달할 경우 참조값이 전달된다.
- 객체의 복사에는 얕은 복사와 깊은 복사가 있다. 얕은 복사의 경우 원시값은 그대로 복사가 되지만, 참조값(객체나 배열 등)은 값 자체 복사가 아니라 주소값이 복사된다. 따라서 참조값은 원본객체와 공유하게 된다.
깊은 복사는 중첩되어 있는 참조값까지 새로 만들어 복사해서 원본객체와 완전히 다른 객체가 생성된다.
let obj = { name : 'kim', arr : [1,2,3]}
let obj2 = {...obj}; // 얕은 복사
obj2.name = 'Lee';
obj2.arr[0] = 5;
console.log(obj); // {name : 'kim', arr : [5,2,3]}
console.log(obj2); // {name : 'Lee', arr : [5,2,3]}
//얕은 복사의 참조값은 주소가 복사되어 원본과 공유한다. 원시값은 원본과 상관이없다.
obj2 = {...obj, arr : [...obj.arr]} // 깊은복사
obj2.name = 'Lee';
obj2.arr[0] = 0;
console.log(obj); // {name : 'kim', arr : [5,2,3]}
console.log(obj2); // {name : 'Lee', arr : [0,2,3]}
//깊은 복사는 참조값까지 모두 별개의 값으로 복사한다.(원본을 훼손하지 않는다.)
9. SpreadSyntax
- 배열이나 객체를 쉽게 합칠 수 있다.
let arr1 = [1,2];
let arr2 = [3,4];
let mergedArr = [...arr1,...arr2];
console.log(mergedArr); // [1,2,3,4]
let obj1 = {name:'kim'};
let obj2 = {age : 100};
let mergedObj = {...obj1, ...obj2};
console.log(mergedObj); // {name : 'kim', age : 100}
- 배열이나 객체를 Spread Syntax로 복사할 때 원시값은 값 자체가 복사되고, 참조값은 주소가 복사(얕은복사) 된다.
let obj = { name : 'kim', arr : [1,2,3]}
let obj2 = {...obj};
obj2.name = 'Lee';
obj2.arr[0] = 5;
console.log(obj); // {name : 'kim', arr : [5,2,3]
console.log(obj2); // {name : 'Lee', arr : [5,2,3]
//참조값은 주소가 복사되어 원본과 공유한다.(얕은 복사)
- rest parameters는 인자를 배열로 받고, arguments객체는 인자를 객체로 받는다.(index를 키값으로 갖는다.)
function rest(...args) {
return args;
}
function argument() {
return arguments;
}
console.log(rest('a', 'b', 'c')); // ['a', 'b', 'c']
console.log(argument('a', 'b', 'c')); // {0:'a', 1:'b', 2:'c'}
10. Destructuring
- 할당하기 전 왼쪽에는 rest문법 이후에 쉼표가 올 수 없다.
let arr = [1,2,3];
let [first,...middle,last] = arr ; // Error : Rest element must be last element
- 객체의 단축 문법, 분해
const name = 'kim';
const age = 100;
const obj = {name, age, height : 199}
console.log(obj); // { name : 'kim', age : 100, height : 199}
const {height,...args} = obj;
console.log(height); // 199
console.log(args) //{ name : 'kim', age : 100}
- 객체를 함수에 인자로 넣을 때 매개변수에 구조분해할당
// 매개변수에 구조분해할당
function intro({name, lesson : course}){ // lesson의 value를 course라는 변수에 넣었다.
return `제 이름은 ${name}이고 원하는 강의는 ${course} 입니다.`
}
let user = { name : 'kim', lesson : 'Frontend' };
console.log(intro(user)); // 제 이름은 kim이고 원하는 강의는 Frontend 입니다.