
📌 프로젝트 만들기
c드라이브 밑에 js폴더 만들기 해당 터미널에서 npm create vite@latest 으로 생성하기 -> 생성한 javascript로 cd -> npm install
export default function doA() {
console.log("doA");
}
<script type="module">
import doA from './sample.js'
doA()
</script>
👉 export는 기존 java의 import와 같은 개념으로 사용된다.
👉 sample.js라는 js파일을 생성하여 메소드를 만드는데, 만약 js에서 메소드를 export할때 default로 생성한다면 html에서 import 메소드를 {}로 가두면 오류가 난다.
👉 {}로 가둘때는 js파일의 메소드를 default를 사용하지 않고 두개이상 사용할때 {}를 사용한다.
export function doA() {
console.log("doA");
}
export function doB() {
console.log("doB");
}
<script type="module">
import {doA,doB} from './sample.js'
doA()
</script>
👉 해당코드처럼 js에서 default를 사용하지 않고 메소드를 두개이상 선언한다면 html에서는 import될 메소드를 {}로 가둬야 오류가 발생하지 않는다
👉 꼭 생성했다고 메소드를 다 사용할 필요는 없다.
👉 js는 인터프리터 언어이다.
👉 js 컴파일 과정에서 두번 읽는데, srcipt태그내에 언어를 읽어서 src를 찾아보고 export가 있다면
script부분만 잘라 할당한 var부분만 먼저 메모리상에 올려놓는다.
👉 이후에 console.log(v1)을 실행하게 된다.
<script>
console.log(v1)
var v1 = 10
</script>
👆 오류발생 x : undefined
<script>
console.log(v1)
let v1 = 10
</script>
👆 오류발생 o : notdefined
📌 var와 let의 호이스팅 개념이 다른점을 이해해야한다.
📌 var의 호이스팅과 메모리 개념은 var를 통해 선언된 변수는 값까지 할당된 내용(var1=10) 전체를 메모리에 할당하는것이 아닌, var1만 메모리 넣은 이후에 두번째로 읽을때 var1(var1=10)에 해당하는 값까지 넣어 메모리에 읽는다. 그러므로 오류는 발생하지 않고 값이 할당되지 않았다는 undefined만 출력된다.
📌 let의 호이스팅과 메모리 개념은 Temporal Dead Zone(TDZ) 라는 개념이 추가되는데, 이는 변수가 실제로 선언되기 전까지 접근할 수 없다. 그렇기 때문에 console에서는 v1값이 메모리상에 할당된것이 아니므로 에러(notdefined) 가 발생한다.
<script>
for(var i = 0; i < 4; i++) {
console.log(i); // 0, 1, 2, 3
}
console.log("-----------");
console.log(i); // 4
</script>
👆 해당 i는 var로 선언되었기 때문에 for루프 외부에서 접근이 가능하다. 고로 var는 사용하지 않는다.
<script>
for(let i = 0; i < 4; i++) {
console.log(i); // 0, 1, 2, 3
}
console.log("-----------");
console.log(i); // ReferenceError
</script>
👆 해당 i는 let으로 선언되어 for루프 외부에서 접근이 불가능하다.
<script>
for(const i = 0; i < 4; i++) {
console.log(i); // TypeError: Assignment to constant variable.
}
console.log("-----------");
console.log(i); // ReferenceError
</script>
👆 해당 i는 const로 선언이 되는데, const는 재할당이 불가능하여 i++와 같이 값이 변경되는것에 사용이 불가능하여 에러가 발생한다.
👉 java에서는 == 등호 두개를 사용하였지만, 이는 값이 동일하냐의 내용으로 js에서도 동일하게 사용된다.
👉 하지만 js에서의 ===는 데이터 타입까지 같은지 확인을 하는데 사용된다.
parseInt('42') -> 42
- parseInt('42px') -> 42
- parseInt는 문자열의 처음부터 유효한 숫자만 추출하여 정수로 변환
NAN이란
- 숫자로 변환할 수 없는 값을 나타내는 특수한 값
<script>
let str = ''
const arr = [1,2,3,4,5]
for (let i = 0; i<arr.length; i++){
str += `<li>${arr[i]*10}</li>`
}
console.log(str)
</script>
<script type="module">
products = [
{pno:1, pname:'오렌지', price:1000},
{pno:2, pname:'사과', price:2000},
{pno:3, pname:'바나나', price:3000},
{pno:4, pname:'포도', price:4000}
]
for (const product of products) {
console.log(product.pno,product.pname,product.price)
}
</script>
👆 해당 코드를 실행하면 에러가 발생한다.
👆 우선 script태그 내에 module을 사용하게 되면, 해당 scripit코드는 module모드로 사용되어 엄격모드에서 실행이된다.
👆 이는 products를 직접 const, let과 같이 데이터타입을 정해주어야 한다.
👆 추가적으로 for문 내부의 product 또한 const와 같이 데이터 타입을 정해주어야한다.
<script>
products = [
{pno:1, pname:'오렌지', price:1000},
{pno:2, pname:'사과', price:2000},
{pno:3, pname:'바나나', price:3000},
{pno:4, pname:'포도', price:4000}
]
for (product of products) {
console.log(product.pno,product.pname,product.price)
}
</script>
👆 만약 type='module'을 사용하지 않는다면 해당 script문 내부에는 데이터타입을 선언해주지 않더라도 에러가 발생하지 않는다.
👆 module을 사용하지 않으면 자동으로 전역모드로 사용되어 var를 통한 데이터타입과 같은 효과를 내면서 데이터타입을 자동으로 설정해준다
📌 이렇게 전역모드 및 전역변수를 사용하게 된다면 내가 원하지 않게 할당된 변수를 외부에서 변경이 가능하므로 전역변수의 사용을 권장하지 않는다.
<script type="module">
const products = [
{pno:1, pname:'오렌지', price:1000},
{pno:2, pname:'사과', price:2000},
{pno:3, pname:'바나나', price:3000},
{pno:4, pname:'포도', price:4000}
]
for (const product of products) { // 1번 방법
console.log(product.pno,product.pname,product.price)
}
for(const{pno,pname,price} of products){ //2번 방법
console.log(pno,pname,price)
}

👆 해당코드처럼 배열을 선언하여 for of문을 통해 변수를 한줄씩 출력이 가능하다.
const products = [
{pno:1, pname:'오렌지', price:1000},
{pno:2, pname:'사과', price:2000},
{pno:3, pname:'바나나', price:3000},
{pno:4, pname:'포도', price:4000}
]
products.map(p=> console.log(p))
//pno:1, pname:'오렌지', price:1000
//...
👆 해당 람다식은 products배열의 제품 객체를 p라 하고 이 전체를 콘솔에 출력한다.
👆 map을 사용하는 이유는 배열의 각 요소를 출력하기 적합하고, 기존 배열을 변경하지 않고 새로운 배열에 기존의 배열의 내용의 변경사항을 적용하여 출력하는 방법.
const result = products.filter(a=> a.price>=3000)
console.log(result)
👆 filter를 이용하여 가격이 3000원 이상인 객체들을 출력가능
const cart = [
{pno:1,qty:2},
{pno:2,qty:3},
{pno:3,qty:1}
]
const cresult = cart.filter(c=> c.qty!==3)
console.log(cresult)
👆 filter를 이용하여 cart 배열내의 qty값이 3이 아닌 객체를 출력
const first = cart.find(c => c.pno === 1)
if(first){
first.qty += 3
}else{
cart.push({pno:1,qty:3})
}
👆 cart배열내에 pno가 1인 값을 찾아서 first라고 선언.
👆 그 first값이 존재한다면 qty(수량)을 3개 증가시키고, 만약 없다면 pno가 1인 값을 qty(수량) 3개를 할당한다.
cart.every(c=>{
const {pno,qty} = c
// cart항목에서 pno와 qty를 추출
const total = products.find(p=>p.pno===pno).price*qty
// total이라는 변수에 product의 pno와 cart의 pno가 같은 price를 찾아 qty를 곱한 값을 선언
c.total = total
//cart항목에 총가격을 추가
return c
//c의 항목들을 출력
})
console.log(cart)
👆 every함수는 배열의 모든 요소가 테스트 함수를 만족하는지 검사.
👆 테스트 함수가 만족하면 true를 반환
const totalAll = cart.reduce((a,b) => {
return a+b.total
},0)
👆 reduce함수는 초기값을 0으로 시작하고, a가 누적값이 되고, b가 현재 값이 된다.
첫번째에서는 a = 0 b = 2000 누적값:2000
두번째에서는 a = 2000 b = 6000 누적값:8000
세번째에서는 a = 8000 b = 3000 누적값:11000으로
totalAll = 11000이 된다.
👉 js에서는 함수 생성시에 받는 파라미터값을 1개 지정하더라도, 호출시 파라미터의 개수는 3개를 해도 에러가 발생하지 않는다.
👉 호출에 해당하는 파라미터가 맞기만하면 상관이 없다.
1. JS에서는 함수는 결국 변수이다.
👉 이때까지 함수를 생성하고 그 함수는 result라는 변수로 사용하겠다. 처럼 사용했으므로 함수는 변수에 할당할 수 있다.
2. 변수의 범위는 함수에 의해 결정된다.(let/const가 나오기전까지)
👉 var를 사용할때는 함수 범위를 사용하고
👉 let,const를 사용할때는 블록 범위를 사용한다. 블록범위는 {} 내에서만 유효
function example() {
if (true) {
var x = 10; // 'x'는 함수 범위에 속함
}
console.log(x); // 10
}
example();
var y = 20; // 전역 범위
function test() {
console.log(y); // 20
}
test();
function outer(){
let current = 10
function inner(){
console.log(current)
}
function change(){
current+=10
inner()
}
return change
}
const change = outer()
change() //20
change() //30
change() //40
const ch2 = outer()
ch2() //20
ch2() //30
ch2() //40
📌 함수의 이동순서
1. change변수는 outer함수를 호출하는 변수로 change()를 통해 outer함수를 호출했다.
2. outer함수가 호출되면서 current = 10 이라는 변수가 메모리에 할당되고, 가장아래 return change를 통해 change함수를 호출한다.
3. change함수가 실행되면서 change함수에는 없지만 closer를 통해 current 변수에 접근할수 있기 때문에 current변수에 10을 더해주고, inner 함수를 호출한다.
4. inner함수를 호출해서 current=20 의 값을 consloe창에 출력한다.
👉 두번째 change()함수 호출부터는 첫번째 change()호출을 통해 생성되었던 current의 값이 20 이였던것이 가장위에있는 current=10을 거치지 않아 초기화 되지않고 바로 함수 호출 change()를 통해 10이 더해지게 된다.
👉 또한, 클로저를 통해 내부 함수가 변수를 할당하지 않더라도 외부함수를 사용할 수 있다. 내부함수에서 변수를 찾는 순서는 local(내부변수) -> 외부변수 -> 전역변수 순서이다.
👉 change()메소드가 끝나기 전까지 current의 값은 메모리에 저장되어있기 때문에 계속적으로 중첩하여 사용할 수 있다.
function outer() {
let current = 10
console.log("new current:"+current)
const inc = () => {
console.log("old current:"+current)
current++
console.log(current)
}
return inc
}
const fn = outer()
fn()
fn()
fn()
👉 fn은 outer를 실행하는것이 아니고 outer의 return값인 inc를 실행하는것.
👉 return inc를 보고 메모리상에 current값이 존재하는것을 확인하여 엔진에서 클로저인지 판단함.