일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- useState
- html
- UX
- React
- 자료구조
- Next.js
- web
- Til
- mysemester
- 백준
- javascript
- 코드스테이츠
- 30daysdowoonchallenge
- CSS
- 해시테이블
- 큐
- vercel
- 운영체제
- 프로그래머스
- level1
- 회고
- 생활코딩
- 카카오
- REST_API
- 자바스크립트
- 스택
- superstarjypnation
- redux
- 프로토타입
- UI
- Today
- Total
데굴데굴
<JavaScript> JavaScript Koans 본문
이번 유닛에서 배운 자바스크립트 주요 문법들을 복습하기 위해 Koans라는 파일로 페어분과 실습을 진행했다.
실습을 하며 새롭게 알게 된 내용들을 정리해보았다. (정확하지 않은 내용이 있을 수 있습니다)
expect 함수
expect(테스트하는값).기대하는조건
expect('1' + '2').to.equal('12')
expect('a' === 'a')to.be.true
// 기대하는 조건 = matcher
// 다양한 matcher가 존재함
코플릿에서 문제를 풀고 제출할 때 테스트코드를 어떻게 작성하나 궁금했는데 expect 함수를 이용한 것이었다. 하나하나 맞을 때마다 KoansRunner파일에 체크표시가 생기는데 거기서 엄청난 희열을 느낄 수 있었다
.deep.equal
과 .equal
.deep.equal은 배열의 요소나 객체의 속성이 서로 같은지 확인하는 matcher이다.
암묵적 타입 변환
자바스크립트는 '+'나 '-' 연산자 사이에 타입이 다른 값들을 넣으면 암묵적으로 타입을 변환한다.
숫자 + 문자열 = 문자열
console.log(1 + "4"); // "14"
➡️ 숫자가 문자열로 변해 뒤의 문자열이 concat된다.
숫자 - 문자열 = 숫자
console.log(143 - "1"); // 142
➡️ 문자열이 숫자로 변해 143 - 1로 계산되어 142가 출력된다.
숫자 + 불리언 = 숫자
console.log(0 + true); // 1
console.log(0 + false); // 0
➡️ true는 숫자의 맥락에서 1, false는 0으로 평가된다.
문자열 + 불리언 = 문자열
console.log("0" + true); // "0true"
console.log("1" + false); // "1false"
➡️ 불리언값이 문자열로 concat된다.
호이스팅
변수 호이스팅
console.log(score); // undefined
var score
자바스크립트 엔진은 변수 선언이 다른 코드보다 먼저 실행된다.
근데 개발자도구에서 해보니 var로 선언했을 때에는 이렇게 undefined가 뜨는데 let으로 선언했을 때에는 ReferenceError가 발생했다.
딥다이브 43페이지에 보면 모든 선언문은 런타임 이전 단계에서 먼저 실행된다고 하는데... 이건 왜 그런걸까...? 🤔
구글링과 딥다이브를 읽으며 관련 내용을 찾았다. (212페이지)
var은 런타임 이전에 선언과 초기화(undefined)가 한번에 이루어진다.
따라서 변수 선언문 이전에 변수를 사용해도 이미 스코프에는 변수가 초기화되어 등록된 상태이기 때문에 오류가 발생하지 않는다.
하지만 let은 다르다.
let으로 변수를 선언하면 선언과 초기화 단계가 분리되어 진행된다.
변수 선언문에서 초기화 단계가 실행되고 이 때 undefined가 할당된다.
위의 경우에서는 초기화 단계 이전에 변수를 참조하려 했기 때문에 ReferenceError가 발생한 것이다.
이렇게 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대(Temporal Dead Zone)이라고 한다.
// 선언 단계 실행, 변수 참조 **불가능**
console.log(height); // ReferenceError 발생
let height; // 초기화 단계 실행 -> undefined가 할당됨.
console.log(height); // undefined
height = 180; // 값이 할당됨
console.log(height); // 180
함수 호이스팅
함수 선언문에서는 호이스팅이 발생하지만, 함수 표현식에서는 호이스팅이 되지 않는다!
함수 표현식에서는 변수 호이스팅이 발생한다. (딥다이브 165페이지 더 읽어보기)
// 함수 선언식
console.log(funcDeclared()); // "함수 선언식입니다."
function funcDeclared() {
return "함수 선언식입니다"
}
// 함수 표현식
console.log(funcExpressed()); // ReferenceError
funcExpressed = function () {
return "함수 표현식입니다"
}
화살표 함수 사용법
화살표 함수는 ES6에서 새롭게 도입된 방법이다. 화살표 함수는 항상 익명 함수로 정의한다. (딥다이브 167페이지)
// function 키워드 생략하고 화살표 붙이기
const add = (x, y) => {
return x + y;
};
// 리턴 생략 가능
const sub = (x, y) => x - y;
// 매개변수가 하나일 경우 소괄호 생략 가능
const add10 = x => x + 10;
화살표 함수로 클로저 표현
// 클로저 표현 1
const adder = (x) => {
return (y) => {
return x + y;
};
};
console.log(adder(10)(20)); // 30
// 클로저 표현 2
const subtractor = (x) => (y) => {
return x - y;
};
console.log(subtractor(25)(15)); // 10
Array의 slice 메소드
slice 메소드의 시작점과 끝에 같은 인덱스를 넣으면 빈 배열이 리턴된다.
const hamburger = ["bread", "patty", "lettuce", "tomato", "bacon"];
hamburger.slice(2, 2); // []
끝 인덱스가 배열의 길이를 초과하면 배열의 끝까지만 출력한다.
hamburger.slice(3, 20); // ["tomato", "bacon"]
시작 인덱스가 끝 인덱스보다 크면 빈 배열이 리턴된다.
hamburger.slice(2, 1); // []
slice에 아무 인자도 넣지 않거나 0을 전달인자로 넣으면 배열 전체를 복사한 새로운 배열을 리턴한다. (주소값이 다르다)
const hamburger2 = hamburger.slice();
console.log(hamburger2); // ["bread", "patty", "lettuce", "tomato", "bacon"]
함수 호출 방식
call by value
인자로 받은 값 그 자체를 복사하여 처리한다.
원시 자료형이 전달인자로 전달될 때 call by value로 처리된다.
call by reference
인자로 받은 값의 주소를 참조한다.
참조 자료형이 전달인자로 전달될 때 call by reference로 처리된다.
객체
객체의 길이?
객체에는 length 메소드를 쓸 수 없다. length 메소드를 써보면 undefined가 리턴된다.
아마 객체는 이터러블이 아니라서 그런 것 같은데 이터러블은 아직 제대로 안 배워봐서 잘 모르겠다.
const person = {
name: 'James',
age: 24,
major: 'SW Engineering'
};
console.log(person.length); // undefined
객체 단축 문법
const name = 'James';
const age = 24
const person = {
name,
age,
major: 'SW Engineering'
};
미리 변수로 선언된 값을 객체에 넣는 경우 굳이 key와 value를 다 써주지 않아도 된다. 위의 person 객체는 그 위 person 객체와 똑같다.
this
this는 여러 정의를 보는 것보다 코드를 직접 보는게 이해하는데 더 도움됐다.
아래는 MDN에서 가져온 예시이다.
const test = {
prop: 42,
func: function() {
// dot notation
return this.prop;
},
};
console.log(test.func()); // 42
객체 안의 func 키의 value는 this.prop을 리턴하고 있다.
나는 this.prop을 약간 문자 그대로 이 객체의 prop키에 할당된 value(여기서는 42)를 리턴한다는 뜻으로 이해했다.
this에서도 객체의 속성에 접근할 때처럼 bracket notation과 dot notation을 적용할 수 있다!
const test = {
prop: 42,
func: function() {
// bracket notation
return this["prop"];
},
};
console.log(test.func());
다른 문제를 푸느라 깊게 공부하지 못해서 자세한 내용은 나도 MDN을 참고하며 더 살펴봐야겠다
new 연산자
new는 생성자 함수, 인스턴스 등 새로운 개념이 많이 엮여있어서 아무리 읽어봐도 뭔 소린지 잘 이해가 안됐다.
향후 다시 공부하기...
(+추가) 새로 배웠다
Spread 문법
ES6에서 새롭게 도입된 문법이다.
배열의 요소를 전부 펼쳐준다.
const spread = ['c', 'd', 'e'];
const arr = ['a', 'b', ...spread, 'f'];
console.log(arr); // ['a', 'b', 'c', 'd', 'e', 'f']
// MDN 예제
function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);
빈 배열에 스프레드 문법을 쓰면 아무것도 전달되지 않는다.
스프레드 문법을 배열을 연결(concatenate)하는 데에 쓸 수도 있다. 객체도 마찬가지이다. (단, 같은 키에 있는 값은 덮어씌워진다)
const abc = ['a', 'b', 'c'];
const def = ['d', 'e', 'f'[;
const alpha = [...abc, ...def];
console.log(alpha) // ['a', 'b', 'c', 'd', 'e', 'f']
Rest Parameter
스프레드 문법을 이용해 함수의 전달인자를 편하게 전달할 수 있다.
단, rest parameter를 쓸 때에는 무조건 rest parameter를 이용한 인자가 마지막에 전달되어야 한다!
구조분해할당 (Destructuring)
객체를 분해할 떄에는 {}, 배열을 분해할 때에는 {}를 쓴다.
스프레드 문법과 레스트 문법은 배열, 객체 분해에도 적용할 수 있다.
객체에 다른 값을 덮어씌워 새로운 객체를 만들 때 유용하게 쓰일 수 있다. (예제 더 추가하기...)
'Programming > JavaScript' 카테고리의 다른 글
<JavaScript> 객체 지향 프로그래밍 (0) | 2022.09.21 |
---|---|
<JavaScript> 클래스와 인스턴스 (0) | 2022.09.21 |
<JavaScript> 원시 자료형과 참조 자료형 (0) | 2022.09.06 |
<JavaScript> 문자열 slice와 substring (0) | 2022.08.27 |
<JavaScript> 타입과 typeof 연산자 (0) | 2022.08.22 |