https://www.youtube.com/watch?v=4_WLS9Lj6n4
해당 포스팅의 모든 캡쳐사진 출처는 위 영상입니다
변수 : var / let / const (var는 예전 버전, 최근엔 let,const 권장)
var는 한번 선언된 변수를 다시 선언할 수 있음 (let은 안됨)
var는 선언하기 전에 사용할 수 있다 : 호이스팅 -> 할당하기 전에 사용하면, 선언은 호이스팅 되지만 할당은 호이스팅 되지 않기 때문에 해당 변수의 값이 undefined로 찍힘
호이스팅 : 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것처럼 행동
*let, const도 사실 호이스팅 된다 ! 하지만 왜 let,const는 선언 전에 사용될 수 없을까? -> let,const는 temporal dead zone의 영향을 받음 ! 이 영역에 있는 변수는 사용 불가 - (코드에서) 선언 전 변수사용 불가
이 코드가 에러를 내는 이유 : 호이스팅은 스코프 단위로 발생 -> 여기서는 showage가 하나의 스코프단위 -> showage내부에선 사용가능한 age가 없음 (만약 let이 호이스팅되지 않는다면, 함수 바깥의 age(30)이 이 함수에 들어와 에러없이 코드가 실행되었을것)
*TDZ (temporal dead zone) : 변수가 선언되고, 초기화되기 전까지의 범위를 tdz에 있다고 얘기함 : let,const가 호이스팅되지 않아서 선언 전에 변수를 사용할 수 없는 것이 아니라, let과 const가 tdz의 영향을 받기 때문에 tdz에 있는 변수들을 사용할 수 없는 것임 !
변수의 생성 과정 : 선언 단계 -> 초기화 단계 -> 할당단계
-> var은 선언과 초기화가 한번에 진행되는 반면, let은 선언과 초기화가 분리되어 진행 (선언단계는 호이스팅이 일어나지만, 초기화단계는 실제 코드에서 변수를 초기화했을때 일어나기 때문에 위의 코드가 error를 내는 것), const는 선언-초기화-할당이 동시에 되어야 함(선언만 하고 나중에 할당하는것 불가능)
스코프
var :함수 스코프 <-> let const : 블록 스코프 : 모든 코드블록 내에서 선언한 변수는 블록 내에서만 유효한 지역변수 (블록 : 함수, if, for, while, try/catch 등)
1) if 안에서 선언한 var는 if 외부에서 사용 가능하지만, const와 let은 불가능 = 블록스코프 의 의미 !
2) var는 함수 스코프 이기 때문에, 유일하게 벗어날 수 없는 스코프가 함수 스코프이다 = 함수 안에서 선언한 변수를 함수 밖에서 사용하는건 불가능
생성자 함수
- 저번 포스팅에서 { } 를 이용해서 객체를 만든게 객체 리터럴 , 한편 비슷한 객체를 여러개 만들어야 하는 일이 있을 수 있음(회원, 상품 여러개 등) -> 그럴때 사용하는게 생성자 함수
- 보통 첫글자를 대문자로 만든다
function User(name,age){
this.name = name;
this.age = age;
}
let user1 = new User('dean',30); //new연산자를 사용해서 객체 호출하여 사용
let user2 = new User('bell',33); //new연산자를 사용해서 객체 호출하여 사용
- 마치 붕어빵틀의 역할을 하는게 생성자함수, 생성되는 객체는 붕어빵
계산된 프로퍼티
- 위의 코드에서 [a]부분은 age 대신 [a]라고 작성한 것 -> [a]는 배열의 의미가 아니라, 변수 a에 할당된 값이 [a]자리에 들어가게 됨 = 계산된 프로퍼티 (computed property)
- 오른쪽 사진처럼 [ ] 안에 식 자체를 넣는것도 가능함
객체 메소드
- object.assign() : 객체 복제
객체를 복제하고자 할때, 왼쪽의 사진처럼 새 변수에 객체명을 대입한다고 객체가 복제되는것이 아님 ! user에는 객체 자체가 들어있는게 아니라 객체의 메모리주소(참조값)이 들어있기 때문 -> user,cloneUser 둘 다 하나의 객체를 접근하게 됨
-> 객체를 복제하고자 한다면 assign() 메소드를 사용해야
위와 같이 코드 작성시 2번째 매개변수가 첫번째 매개변수(빈 객체) 에 병합됨 -> 복제되는 결과
첫 매개변수에 프로퍼티값을 1개 넣는다면 - 총 3개의 프로퍼티를 가진 새 객체가 생김
만약 병합 시 같은 키가 두개 라면 -> 후자의 키로 덮어쓰게됨
매개변수가 3개일 수도 있음 = 후자의 것이 맨 처음에 병합되는 식
2. object.keys() : 키 배열 반환
-> object.keys(user) -> 키값들을 배열에 담아서 반환
3. object.values() : 값 배열 반환
4. object.entries() : 키/값 배열 반환 -> 배열 안에 키/값으로 이뤄진 배열들이 있는 형태가 반환됨
5.object.fromEntries(배열명) : entries와 반대로, 키/값 배열을 객체로 만들어줌
위의 내용들 사용 예시 : 함수 호출 시 첫 인자로 넣은 값이 key의 이름이 됨 -> [ ]는 어떤게 키 이름이 될지 모르는 객체를 만들때 유용함
심볼
- 여태까지는 객체의 프로퍼티 키를 문자형으로 만들었음 -> 키에 1이나 false 등 숫자,boolean형을 써도 키를 반환해보면 문자형으로 반환됨 ("1", "false") -> 실제 접근시에도 문자 1, 문자 false로 접근함
- 객체의 프로퍼티 키는 위와같이 문자형, 혹은 심볼형으로 가능함
- 심볼은 유일한 식별자에 사용함
- 심볼 생성시엔 new 붙이지 않고, 그냥 const a = Symbol(); -> Symbol()로 const 2개 만들어서 일치연산자(===) 넣어보면 둘이 다르다고 나옴 , 동등연산자(==)에도 둘이 다르다고 나옴
- 심볼 : 유일성이 보장됨
- 심볼 생성시 매개변수에 문자형으로 설명 넣을 수 있는데, 설명이 같아도 두개의 심볼은 서로 다른 존재로 취급됨
- 위와 같이 심볼형으로 키를 만들었을때, 멤버접근은 정상적으로 가능하지만 key를 찍어보면 name과 age만 출력됨 ->keys(), values(), entries(), for in 은 symbol형으로 된 프로퍼티는 건너뜀
- 그렇다면 심볼형으로 된 프로퍼티를 어디에 사용할까? 특정 객체에 원본 객체는 건드리지 않고 자신만의 속성을 추가할 때 사용 ! (원본 객체를 덮어써버리는 일이 발생하지 않음)
- Symbol.for() : 전역 심볼 -> 하나의 심볼만 보장받을 수 있음 , 즉 Symbol() 함수는 매번 다른 심볼값을 생성하지만 이 메소드는 하나를 생성한 뒤 키를 통해 같은 심볼을 공유
- Symbol.for('id')로 심볼을 두번 생성해도, 두 심볼이 같은 존재로 취급됨
- Symbol.for()로 객체 생성한 경우 keyFor()를 사용해 심볼 생성 시 적은 이름을 반환받을 수 있음
- 전역심볼 아닌 경우는 keyFor()대신 description()으로 이름 알 수 있음
- 숨겨진 심볼 키 보는 법 : getOwnPropertySymbols(user), ownKeys(user) 메소드 이용 (잘 사용하진 않음)
- 이 예제에서, 9-11 줄 대신 주석처리된 8줄로 코드를 실행하면 16번줄의 실행결과로 his showname is function{ }이라는 말도 안되는 결과가 포함됨 -> showName 함수를 심볼로 만들면 16번줄의 결과가 올바르게 나옴, 즉 다른 코드에 영향을 주지 않는 방식으로 객체에 메소드를 추가하게 됨
Number, Math
- 10진수를 2진수/16진수로 바꾸려면?
- toString()메소드를 사용하되, 매개변수에 n을 넣으면 수를 n진수로 변환됨
- Math.sail() : 소수점 올림
- Math.floor() : 소수점 내림(소수점 이하를 버림)
- Math.round() : 반올림
- 소수점 셋째자리에서반올림하여 둘째자리까지 표현 : 100을 곱해서 반올림 (셋째자리에서 반올림->3012) 후 다시 100을 나눔 (원래 소수점대로 표현)
- toFixed(n) : 숫자를 받아서 n번째 자리까지만 표현 (전자에 비해 훨씬 간단)
- toFixed()의 주의점 : 숫자가 아닌 문자를 반환함 -> 메소드 사용 후 Number()로 형변환해서 사용하는 경우가 많음
- isNaN() : 값이 nan인지 아닌지 변환 (값이 nan인지 아닌지 확인 가능한 유일한 방법)
- parseInt() : 문자를 숫자로, Number()와의 차이는 받은 값에 문자와 숫자가 혼용되어 있어도 동작을 함
- parseInt는 읽을 수 있는데까지 읽고, 문자를 만나면 숫자로 바꿈
- 글자가 숫자가 아닌 문자로 시작하면 nan을 반환
- parseint는 두번째 인수를 받아서 진수를 지정 가능 : parseInt('f3',16)을 하면 16진수로 취급돼서 243반환, parseint('11',2) 하면 11이 2진수로 취급돼서 3이 반환됨 (11(이진수)에 해당하는 십진수)
- parseFloat() : 부동소수점을 반환 (18.5% -> 18.5 로 반환됨)
- Math.random() ; 0-1사이의 무작위 수를 반환
- 1-100 사이 임의의 숫자를 뽑고 싶다면 : Math.floor(Math.random()*100 )+1 로 식을 적절히 만들어서 사용해야함
- Math,max(), Math.min() - () 안의 인수들 중 최대값/최소값을 반환
- Math.abs() : 절댓값 구해줌
- Math.pow(n,m) : n의 m제곱 값 구해줌
- Math.sqrt() : 제곱근 구해줌 (루트)
문자열 메소드
- 문자열 : ' ' , " " , ` ` 으로 표현
- ' '와 " "는 큰 차이 없음
- ` ` : 여러줄 표현 가능, ${} 사용 가능
- length: 문자열 길이
- 특정 위치에 접근 : 문자열명[n] 으로 접근 , 인덱스는 0부터 시작, 그러나 배열과 다르게 문자열 중 한 글자만 바꿀 수 없음
- toUpperCase(), toLowerCase() : 모든 영문을 대문자로 / 소문자로
- str.indexOf() : 매개변수로 들어온 문자의 위치(인덱스) 반환, 들어온 문자 여러글자라도 첫 문자의 위치만 반환, 매개변수의 문자 없는 경우는 -1 반환
- indexOf() 를 if에 쓸땐 인덱스가 0부터 시작한다는 것에 주의 ! 0은 if의 조건에서 false로 취급되기 때문 - 보통 값이 -1보다 큰지로 if문에서 특정 문자의 포함여부를 판단함
- str.slice(n,m) : n부터 m 위치까지의 문자를 잘라서 반환 , m 없으면 끝까지 반환, 양수면 그 숫자 인덱스 직전까지, m이 음수면 끝에서부터 셈
- str.substring(n,m) : n과 m위치 사이의 문자 반환 - n과 m 바꿔도 동작(시작/끝이 아니라 n과 m '사이'로 인식하면 편함), 음수 허용 x - 음수는 0으로 인식함
- str.substr(n,m) : n부터 시작 - m개를 가져옴
- str.trim() : 문자열 앞 뒤 공백을 제거
- 문자열 비교 가능 : 아스키코드의 코드값을 기준으로 비교 ( 'a' < 'c')
- 문자.codePointAt(0) : 문자의 아스키코드값을 알려줌
- String.fromCodePoint(숫자) : 아스키코드값(숫자)를 문자로 바꿔줌
- let newList = [] ; // 빈 배열 생성
배열 메소드
- arr.splice(n,m) : n번째 인덱스 요소부터 m개를 지운다
- arr.splice(n,m,x) : 특정 요소 지우고 그 자리에 x를 추가(맨 앞의 두 매개변수 이후부턴 모두 x) / 아무것도 지우지 않고 추가만 하고 싶다면 m을 0으로
- splice()는 삭제된 요소를 배열로 묶어 반환함
- arr.slice(n,m) : 인덱스 n부터 m까지 반환 -> m은 포함하지 않음, m 안쓰면 배열 끝까지 반환
- arr.concat(arr2,arr3) : 인자로 주어진 배열을 arr에 합쳐서 새 배열 반환 (인자는 배열이 아닌 그냥 자료형일수도 있음
- arr.forEach(fn) / arr.forEach((item,index,arr)=>{ }); : 배열 반복 , 함수를 인수로 받음 -> 3개의 매개변수(요소,인덱스, 배열)가 있는 함수 , 보통 앞 2개의 매개변수만 사용
- arr.indexOf / arr.lastIndexOf : 매개변수에 해당하는 요소가 있는 인덱스 반환 , 매개변수 두개면 뒤 매개변수 위치에서부터 앞의 요소를 탐색하라는 의미, 끝에서부터 탐색하고 싶으면 lastIndexOf 사용
- arr.includes() : 매개변수에 해당하는 요소를 포함하는지 확인만 하고싶을때 사용
- arr.find(fn) / arr.findIndex(fn) : 요소 혹은 인덱스를 찾음, 더 복잡한 연산이 가능하도록 매개변수가 함수형태, 주의점은 첫번째 true 값만 반환하고 끝임 / 없으면 undefined를 반환
요소(1-5)를 순회하면서 함수 본문이 true일때에 해당하는 요소를 반환 (첫 true만 반환하고 끝) -> 2가 반환됨
- 만약 조건을 만족하는 모든 요소를 반환받고 싶다면 -> arr.filter(fn) 함수 사용 ! (사용법은 동일)
- arr.reverse() : 역순으로 재정렬 (최근 가입한 유저부터 보여주거나, 최근 작성된 글부터 보여줄때 주로 사용)
- arr.map(fn) : 함수를 매개변수로 받아서 특정 기능을 시행하고 새로운 배열을 반환
- 배열 요소들을 이어서 문자열로 만들고 싶을때 : arr.jon() 사용 -> 매개변수로 전달하는게 구분자, 매개변수 안쓰면 쉼표(,)로 구분
- arr.split() : 위와 반대로, 문자열을 나눠서 배열로 만들어줌 -> 매개변수에 들어가는게 구분자, 구분자를 기준으로 문자열을 나눔
- 배열인지 아닌지 확인 : array.isArray() (비교 : typeOf를 사용하면 객체라고만 알려줌 -> 다른 객체와 배열 비교 불가)
- arr.sort() : 배열 재정렬(숫자는 오름차순으로, 문자는 알파벳순으로) -> 배열 원본 자체가 변경되는점 주의
let so = [4,5,2,6];
so.sort();
console.log(so);
let so2 = [27,8,5,13];
so2.sort();
console.log(so2); //[13,27,5,8] 출력됨
위의 코드에서, so의 정렬은 제대로 되는데, so2의 정렬은 제대로 이뤄지지 않는다
-> sort함수는 정렬하기 전에 배열 내의 값을 내부적으로 문자열로 변환한다는 사실 때문 !
문자 비교에서는 (사전식) 첫 번째 글자가 크면 더 큰 결과가 되기 때문에(자릿수 고려 x) 위와같은 결과가 나오는 것
=> 숫자 배열을 올바르게 정렬하려면 ? 인자로 정렬 기준을 나타내는 콜백 함수를 받는 방식 사용
: 두 인자를 비교하여, 첫번째인자 < 두번째인자 이면 음수를 / 첫번째인자>두번째 인자이면 양수를 / 같으면 0을 반환하는 규칙
let so2 = [27,8,5,13];
// so2.sort(fn)
// sort 함수 : 두 요소를 전달하고, 크기를 비교하여 뭐가 큰지 확인 -> a,b 비교해서 a가 작으면 (리턴값 음수) a를 b 앞 인덱스로, a가 더 크면(리턴값 양수) 반대로 a를 뒤로
so2.sort( (a,b)=>{
return a-b;
}
);
console.log(so2);
위와 같이 수정하면 올바르게 정렬된다
: 27, 8 비교 하니까 8이 작아서 8을 앞으로 보냄 -> 5와 8을 비교하니 5가 작아서 5를 앞으로 -> .. 이 과정을 반복하도록 sort함수가 설계되어 있음
*내림차순으로 정렬하고 싶다면 a-b를 b-a로 바꾸면 됨 (sort함수는 리턴값의 음양을 기준으로 작동하니까 = 리턴값이 음수이면 a를 b보다 앞 인덱스로, 리턴값이 양수이면 a를 b보다 뒤 인덱스로 보냄)
=> 이러한 기능을 더 간편하게 이용하기 위해 lodash와 같은 라이브러리 이용 (_.sortBy(arr)로 가능)
#콜백함수란 ?
- 파라미터(인자)로 함수를 전달하는 함수
- 다른 함수에 매개변수로 넘겨준 함수
- 매개변수로 일단 함수를 넘겨받고, 때가 되면 나중에 호출(called back)한다는 의미
#js에서 함수는 객체이다 , 따라서
- 변수나 데이터 안에 담길 수 있다
- 매개변수로 전달할 수 있다 : 함수에 파라미터로 객체를 전달할 수 있다 -> 함수는 객체이다 -> 함수의 파라미터로 또다른 함수를 전달할 수 있다 => 이때 매개변수인 함수를 콜백함수라고
- 반환값으로 함수가 사용될 수 있다
배열 메소드 2
- arr.reduce() : 배열을 돌면서 원하는 작업을 하고 최종값(누적값)을 반환함 - 매개변수로 함수 들어감
//reduce의 첫 매개변수는 함수, 두번째 매개변수는 0
//prev는 현재까지 누적된 값
//prev의 초기값은 0 (두번째 매개변수)
//현재까지 누적된 값에 요소들을 차례로 더하는 함수를 콜백함수로 넣음
const result = arr.reduce( (prev,cur)=>{
return prev+cur;
},0)
console.log(result);
reduce의 정의
array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
//reduce 함수의 두 번째 인자인 initialValue가 초기값입니다. 만약 initialValue를 제공하지 않으면, 배열의 첫 번째 요소가 초기값이 되며, reduce 함수는 두 번째 요소부터 시작합니다.
//callback 함수는 네 개의 매개변수를 받습니다:
//accumulator: 누적된 값으로, 현재까지의 계산 결과가 여기에 누적됩니다.
//currentValue: 현재 배열의 요소입니다.
//currentIndex: 현재 배열의 요소의 인덱스입니다.
//array: reduce를 호출한 배열 자체입니다.
//초기값이 제공된 경우, accumulator는 초기값으로 시작하고, 그렇지 않으면 배열의 첫 번째 요소가 accumulator로 사용됩니다.
//따라서 reduce 함수의 동작은 초기값을 이용하여 배열의 각 요소에 대해 주어진 콜백 함수를 실행하고 누적값을 계산하는 것입니다.
'dev > 프론트엔드' 카테고리의 다른 글
코딩앙마 리액트 강좌 정리 (1) (0) | 2024.02.12 |
---|---|
Javascript 중급강좌 정리(2) : 완강 ! (0) | 2024.02.03 |
Javascript 기초 강좌 정리 (0) | 2024.01.23 |
CSS (0) | 2024.01.22 |
html : semantic tag, inline vs block element (0) | 2024.01.16 |