코드스테이츠

1/4 일일정리 Javascript Koans

강물둘기 2023. 1. 4. 16:24

페어와 함께 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 입니다.