
진짜! 자바스크립트(Javascript) - 기초부터 고급까지
₩99,000
입문 / JavaScript, ES6, es5, 객체지향
4.9
(38)
🌟 자바스크립트의 기초부터 고급까지, 진짜! 자바스크립트 강의에서 시작하세요! 🌟
입문
JavaScript, ES6, es5
안녕하세요. 유튜브에서 즐거운 코딩 경험 - 코딩맥스(CodingMax) 채널을 운영하고 있는 코딩맥스입니다. 삶을 살아 가면서 새로운 지식을 배우고 나누는 것을 좋아 합니다. 😊
📺 https://www.youtube.com/@coding-max
항상 유익하고 알찬 내용으로 찾아 뵐게요!
질문&답변
코드 샌드박스 소스 입력시 콘솔이 계속 반응하는것 같아요.
ymckh1005님 저도 신규 프로젝트 생성 후 재현에 성공하여 해당 내용을 끄는 방법을 찾아 보았습니다.아래 이미지에서 빨간색 사각형으로 표시한 버튼과 메뉴를 클릭해서 Settings 로 진입합니다. (사진) search settings 입력란에 preview 라고 입력합니다.(사진) 그러면 설정 중에 Sandbox: Preview Run Action 이 있는데요(사진) 기본값이 edit-delayed 를 Save 로 변경합니다.(사진) 이렇게 설정하고 Settings 를 닫고 편집해 보시면, Preview 가 업데이트 되지 않고 저장할 때만 업데이트 되는 것을 알 수 있습니다. 위처럼 했는데 동작하지 않는다면, 화면을 리프레시 하거나 프로젝트를 닫았다가 다시 열어보면 설정대로 동작할 것입니다. 감사합니다 🙇♂
질문&답변
코드 샌드박스 소스 입력시 콘솔이 계속 반응하는것 같아요.
안녕하세요 ymckh1005님, 인프런 AI 인턴의 답변은 AI 가 작성하여 정확하지 않을 때가 있습니다. 우선 불편을 드려 죄송합니다.제가 MacOS 환경의 크롬에서 코드 샌드박스를 실행하면, 코드를 작성할 때는 console.log가 반응하진 않고 Cmd+S 를 눌렀을 때에만 작동했습니다. ymckh1005님이 겪으신 불편을 제가 재현하지 못한 이유가 코드샌드박스 업데이트가 잦아서 생긴 버그 일 수 있습니다. 처음 문의 주신 것처럼 로컬에 수업환경을 만들고 VSCode 로 수업을 진행하시는 것을 추천드립니다. 관련하여 아래 영상들을 참고 하시면 좋을 것 같습니다. 감사합니다. 🙇♂로컬 수업 환경을 위한 nodejs 설치하기 nvm 으로 nodejs 설치하기 Parcel로 로컬 수업 환경 만들기Vite로 로컬 수업 환경 만들기
질문&답변
배열 생성자로 배열 생성시 empty와 undefined
안녕하세요. 807연구실님! 질문 주셔서 감사합니다.먼저 평일에는 제가 답변을 빨리 못 드리는 점 양해 부탁드립니다.배열 생성자로 생성시 empty 와 undefined 에 관해서 질문 주셨는데요. 먼저 답변을 드리면, empty 와 undefined 는 서로 다른 것입니다.자바스크립트에서 undefined 는 엄연한 값입니다. 강의 중에 V8은 undefined, null 그리고 string 을 어떻게 관리할까 편을 보시면, undefined 가 어떻게 생성되고 관리되는지 아실 수 있습니다.그렇다면 배열을 생성자로 생성시 empty 는 무엇인지 좀 더 알아 보겠습니다.자바스크립트로 배열 생성할 때, 우리는 꽉 찬 배열과 구멍이 존재하는 배열을 생성할 수 있습니다.// 꽉 찬 배열 const array = [1, 2, 3];// 구멍이 있는 배열, 일명 Sparse Array const array = new Array(3);Sparse Array 는 모든 인덱스에 할당 된 값이 없을 수 있는 배열을 말합니다. 즉, 구멍이 있는 배열이죠. 예를 들어, 1번 인덱스에 값이 없는 배열은 아래와 같습니다.[0, ,2]위 표기법에서 값이 할당되지 않았다는 것을 표시하기 위해서 자바스크립트는 empty 를 사용합니다.[0, empty, 2]이와 다르게, 아래 배열은 1번 인덱스에 undefined 라는 값을 가지고 있는 것입니다.[0, undefined, 2]즉, 자바스크립트에서 값이 있다는 것은 메모리를 할당 받았다는 것을 의미하기 때문에 empty 는 메모리를 할당 받지 않은 것(배열의 슬롯)을 의미합니다.중요한 것은 왜 이렇게 되어야 했을까를 이해하는 것입니다.사실 자바스크립트 배열은 객체입니다. 우리가 흔히 아래처럼 객체 리터럴로 표시하는 바로 그 객체입니다.const obj = {};[1, 2, 3] 을 객체로 표현하면 아래와 같습니다.const arrayObj = { 0: 1, 1: 2, 2: 3 }즉, 인덱스를 속성키 이름으로 갖는 객체입니다. 그래서 아래와 같이 접근 가능합니다.arrayObj[0] // 1 입니다. arrayObj[1] // 2 입니다. arrayObj[2] // 3 입니다.여기에 추가로 length 라는 속성을 추가하면 자바스크립트에서 배열과 비슷한 객체라고 해서 array-like object 를 만들 수 있습니다.const arrayLikeObj = { 0: 1, 1: 2, 2: 3, length: 3 }array-like object 는 특별한 것이 없지만, Array.from 등을 통해서 Array 객체로 쉽게 변환할 수 있습니다.Array.from은 첫 번째 인자로, iterable 또는 arrayLike 객체를 받아서 배열로 반환합니다.그래서 아래와 같이 하면 빈 배열이 반환됩니다.Array.from({ 0: 1, 1: 2, 2: 3, }) // [] 이 반환됩니다.하지만 length 를 추가하면 [1, 2, 3] 배열이 반환됩니다.Array.from({ 0: 1, 1: 2, 2: 3, length: 3 }); // [1, 2, 3] 이 반환됩니다.대표적인 Array Like 객체가 function 객체의 arguments 입니다. function 함수 객체가 받는 인자를 Array Like 객체 형태로 담고 있습니다. 그리고 document 의 querySelectorAll 이 반환하는 NodeList 도 Array Like 객체입니다.const nodeList = document.querySelectorAll('div'); Array.isArray(nodeList); // false 'length' in nodeList; // true이렇듯 자바스크립트는 객체를 사용해 배열을 표현합니다. C언어와 같은 언어에서는 연속적인 메모리 블럭이 배열인 것과 다른 점입니다.그렇다면, 자바스크립트에서 배열이 왜 sparse array 즉, 구멍이 존재할 수 있는 배열인지 이해할 수 있습니다.아래와 같이 배열을 생성해 봅시다.const bigArray = new Array(1000000000);10억 개입니다. 참고로 배열 생성자로 생성할 수 있는 최대 길이는 2^32 - 1 개입니다. 배열이 길이가 32비트 부호 없는 정수로 표현되기 때문입니다. 배열 생성자로 10억개를 생성할 때, 모든 원소에 대해서 메모리를 할당하면 어떻게 될까요? 1개의 원소가 1byte 만 차지해도 0.9 GB 로 약 1GB 의 메모리를 사용하게 됩니다.const bigArray = { 0: 어떤값, 1: ... ... 999999999: 어떤값 }자바스크립트는 태생이 브라우저 안에서 실행되는 작은 스크립트 언어였습니다. 즉, 브라우저의 프로세스 내부에서 실행되는 것이었죠. 자바스크립트가 위처럼 크게 메모리를 할당하면, 브라우저가 뻗거나 꺼지거나 하는 일이 발생할 것입니다.그리고 메모리 할당과 해제를 해야하기 때문에 브라우저의 속도가 매우 느려졌을 것입니다. 그리고 자바스크립트는 꽤 오래전에 탄생한 언어이기 때문에, 그 당시 PC는 메모리가 충분하지 않았습니다.모든 배열 생성에 브라우저 프로세스에 영향을 주지 않은채 충분한 메모리를 사용하기란 불가능했을 것입니다.그래서 자바스크립트는 객체로 배열을 표현하고, 객체의 키를 인덱스로 사용하기로 한 것입니다.그래서 아래와 같은 일이 가능한 것입니다.const arr = [1, 2, 3]; arr[999999999] = 10;arr 은 아래와 같이 구멍이 존재하는 sparse array 가 되는 것이죠.[1, 2, 3, empty × 999999996, 10]즉, 1, 2, 3, 10 을 제외하고 다른 자리(슬롯)에는 메모리가 할당되지 않은 것을 나타내는 empty 를 표시하는 것입니다.자 여기서 확인해 볼 내용은 위에서 생성한 arr의 길이는 몇 일까요?arr.length // 1000000000 입니다.즉, arr 을 객체로 표현하면const arr = { 0: 1, 1: 2, 2: 3, 999999999: 10, length: 4 }가 아니라const arr = { 0: 1, 1: 2, 2: 3, 999999999: 10, length: 1000000000 }라는 점입니다. 아래 코드를 실행하면,arr.forEach((value, i) => console.log(value, i)); 1 0 2 1 3 2까지는 빨리 출력되지만, 조금 시간이 지난 후에10 999999999이 출력됩니다. 즉, forEach 는 length 횟수만큼 실행하지만, empty 에 대해서는 콜백함수를 실행하지 않기 때문입니다.만약 empty 대신 에 undefined 를 갖고 있다고 해 볼게요.const bigArr = new Array(1000000000).fill(undefined);위 코드를 실행해 보시면, 아래 그림처럼 브라우저가 뻗는 것을 확인할 수 있습니다. 10억개의 메모리를 할당하다가 뻗는 것이죠.(사진) 이렇게 해서 sparse array 에서 empty 와 undefined 가 서로 다르다는 것과 empty 의 의미, 그리고 sparse array 가 자바스크립트에서 필요했던 역사적인 내용 등을 같이 알아 보았습니다.답변이 도움이 되었길 바랍니다.감사합니다.답변을 적고 수업을 확인해 보니 수업 중에서는 아래 코드가 undefined 로 초기화 된 배열을 출력하고 있었네요. const fiveItems = new Array(5); console.log(fiveItems); // [undefined, undefined, undefined, undefined, undefined]하지만 이는 코드샌드박스의 보정으로 아래와 같이 실행된 것과 동일합니다.const fiveItems = new Array(5).fill(undefined); console.log(fiveItems);아무래도 Babel 의 트랜스파일러 영향인 것 같습니다.만약 보정이 없다면,const fiveItems = new Array(5); console.log(fiveItems);는 아래와 같이 empty 가 5개 있는 sparse array 가 되어야 합니다.[empty x 5]혼란을 드린 점 죄송합니다. 관련 정정 내용은 수업 노트로 추가하였습니다.감사합니다.
질문&답변
nvm 설치 오류입니다.
ttyykim님 윈도우를 사용하고 계신군요 그렇다면, nvm-windows 를 설치하셔서 사용하시면 됩니다. 아래 주소의 Release 페이지에서 다운로드 하실 수 있습니다.https://github.com/coreybutler/nvm-windows1.2.2 최신 버전이어서 아래 주소로 가셔서 nvm-setup.exe 를 받아서 설치해 주세요!https://github.com/coreybutler/nvm-windows/releases/tag/1.2.2(사진)설치 후 아래 명령어 입력으로 nvm 버전이 잘 출력되면, 설치가 완료된 것입니다.nvm --version감사합니다.
질문&답변
console 이 안보입니다.
안녕하세요. ttyykim 님 질문 주셔서 감사합니다.코드박스가 자주 업데이트 되어 UI 구성이 강의와 다를 수 있습니다. 우선 콘솔은 아래 순서로 확인하실 수 있습니다.(사진) 수업은 코드샌드 박스로 진행하고 있지만 로컬에 수업 환경을 만들고 강의를 수강하셔도 괜찮습니다.섹션3에서 로컬 환경에서 수강 환경 만들기 내용이 있으니 참고하시면 좋을 것 같습니다.감사합니다.
질문&답변
then 메서드에서 Promise 를 반환하는 코드에 대한 질문입니다.
안녕하세요. Droid 님 질문 주셔서 감사합니다! 😊then() 메서드의 반환값을 좀 더 자세히 살펴보겠습니다. new Promise((resolve, reject) => { resolve(10); }) 하면 결과로 fulfilled 상태의 Promise 가 반환되는 것을 아실 것입니다. Promise {: undefined} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: undefined 해당 내용은 아래 강좌에서 다루었습니다.Promise의 3가지 상태Promise 메서드 체이닝강좌에서는 then() 메서드에서 Promise 를 반환하는 경우만 다루었는데요. 아래와 같이 일반 값을 반환하면 어떻게 될까요? new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return value * 2; }) 이 때에도 fulfilled 상태의 Promise 가 반환됩니다. Promise {: 20} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: 20 Promise 가 아닌 값을 반환했는데 Promise 가 반환됩니다. 이 것은 then() 메서드에서 일반 값을 반환할 경우, 자동으로 Promise.resolve 로 한 번 감싸기 때문입니다. 즉, 아래와 같은 것이죠. new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return Promise.resolve(value * 2); }) 그래서 아래와 같이 계속 then() 메서드를 체이닝해서 사용할 수 있습니다. new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return Promise.resolve(value * 2); }) .then((value) => console.log(`값이 도착했습니다. ${value}`))아무것도 반환하지 않을 경우는 어떨까요? 자바스크립트에서 함수가 아무 것도 반환하지 않더라도 undefined 를 반환합니다. function a() {} a() // undefined 를 반환합니다. 그래서 아래와 같이 then 메서드에서 아무 것도 반환하지 않더라도 new Promise((resolve, reject) => { resolve(10); }) .then((value) => { console.log(value); }) undefined 가 반환되고 then 에서 반환된 값은 자동으로 Promise.resolve() 로 감싸집니다. new Promise((resolve, reject) => { resolve(10); }) .then((value) => { console.log(value); return Promise.resolve(); }) 위 코드처럼 실행됩니다. 그래서 반환값으로 undefined 를 PromiseResult 로 갖는 fulfilled 상태의 Promise 가 반환되는 것입니다. Promise {: undefined} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: undefined 만약 일반 값이 아닌 Error 를 throw 하면 어떻게 될까요? new Promise((resolve, reject) => { resolve(10); }) .then((value) => { throw new Error('오류가 발생했습니다'); }) 이 때는 상태가 'rejected' 인 Promise 가 반환됩니다. Promise {: Error: 오류가 발생했습니다.} [[Prototype]]: Promise [[PromiseState]]: "rejected" [[PromiseResult]]: Error: 오류가 발생했습니다. 즉, 일반값을 반환하거나 오류를 throw 하면 자동으로 Promise 로 감싸지는 것을 알 수 있습니다. 그렇기 때문에 Promise 의 메서드인 then 또는 catch 를 체이닝을 통해서 사용할 수 있는 것입니다.자 그럼 새로운 Promise 를 반환할 때는 언제인가요? 새로운 비동기 작업이 필요할 때입니다. 그런데 이 때, 주의 깊게 생각해 볼 문제가 있습니다.만약 Promise 를 반환하는데 일반값이나 오류 throw 일 때처럼 Promise 로 감싸면 어떻게 될까요? new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return new Promise((resolve, reject) => { setTimeout(() => resolve(value * 2), 1000); }); }) 만약 then 메서드가 반환하는 Promise 를 다시 Promise 로 감싼다면, Promise, Error> 처럼 될 것입니다. 즉, 배열의 배열처럼 [array, [of, [array]]] Promise 가 계속 쌓이게 되는 것입니다.그렇게 되면 다음 then() 에서 아래와 같이 사용해야 할 것 입니다. new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return new Promise((resolve, reject) => { setTimeout(() => resolve(value * 2), 1000); }); }) .then((if_promise) => { if_promise.then(value => { console.log(value); }) }) 하지만 뭔가 이상하지 않나요? 네 그렇습니다. 만약 Promise 를 위처럼 사용해야 한다면 '콜백헬'에서 발생했던, 깊이가 깊어지는 문제가 다시 발생합니다.그래서 Promise 는 [array, [of, [array]]] 의 flat() 메서드처럼 중첩된 Promise 를 flat 하게 펴주는 기능을 자동으로 제공합니다. ['array', ['of', ['array']]].flat(Infinity) // 출력결과 ['array', 'of', 'array'] 그래서 아래와 같이 then() 메서드에서 Promise 를 반환하면, new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return new Promise((resolve, reject) => { setTimeout(() => resolve(value * 2), 1000); }); }) Promise, Error> 가 flat 되어 Promise 가 반환됩니다. 그래서 결과가 아래와 같죠. Promise {} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: 20 PromiseResult 로 값은 20이 있지만, Promise 가 pending 상태에 있기 때문에, then 을 통해서 값을 얻어야 합니다. new Promise((resolve, reject) => { resolve(10); }) .then((value) => { return new Promise((resolve, reject) => { setTimeout(() => resolve(value * 2), 1000); }); }) .then((value) => console.log(value)); 그러면, 1초 뒤에 콘솔에 '20' 이 출력됩니다. 따라서 정리해 보면, Promise 는 then 메서드나 catch 메서드에서 일반값을 반환하거나 Error 를 throw 하면 Promise 로 자동으로 감싸서 반환합니다. 그래서 then 이나 catch 를 사용해서 계속 체이닝을 이어갈 수 있습니다.그리고 then 메서드나 catch 메서드에서 Promise 를 반환하면 자동으로 flat 을 실행해 중첩이 없는 Promise 를 반환합니다. 그래서 콜백헬에서 나타나는 깊이가 깊어지는 문제를 해결합니다.여기에서 잠깐 나온 Promise 를 반환하면 자동으로 flat 을 실행해 중첩이 없는 Promise 를 반환하는 내용은 모나드의 map 과 flatMap 과 비슷합니다. 즉, Promise 의 then 이 map 연산자와 비슷하면서도 반환값에 대해서는 flatMap 기능을 수행해 주는 것과 비슷합니다.참고로, 모나드에 대한 내용은 Result 타입과 모나드 강좌에서 다루고 있습니다.https://www.inflearn.com/courses/lecture?courseId=331739&unitId=182191&subtitleLanguage=ko답변이 도움 되었기를 바랍니다. 감사합니다.
질문&답변
for 문에서 var 키워드 변수를 사용할 때와 let 키워드 변수를 사용할 때 차이점
안녕하세요 Droid 님! 질문 주셔서 감사합니다 😊 해당 내용은 현재 수강하고 계신 강좌 중 아래 강좌에서 자세한 내용을 설명하고 있습니다. 변수 스코프(함수 스코프와 블록 스코프) 그리고 VAR 변수의 문제점 1편 📕강좌의 10분정도 위치에 for 문의 let 변수가 어떻게 바인딩이 되는지 그리고 setTimeout 의 콜백함수에 어떻게 캡쳐링이 되는지 설명을 하고 있습니다.함수 실행 컨텍스트 2편 - 다시 보는 함수 스코프와 블록 스코프📕 함수 실행 컨텍스트를 다루며 같은 문제를 좀 더 자세하게 설명하고 있습니다. 스코프 체이닝(Scope Chaining)은 언제 실행될까? 와 관련된 중요한 문제와 해결법📕추가로 이 강의도 같이 보시면 좋을 것 같습니다 감사합니다 😊
질문&답변
Global 스코프 질문
안녕하세요! 팀오님! 질문 주셔서 감사합니다.팀오님이 이해하신 내용이 맞습니다. 거기에 약간 살을 붙여 설명을 드리겠습니다. 자바스크립트의 글로벌 스코프는 하나이지만 이해를 돕기 위해 var 변수를 관리하는 글로벌 스코프가 있고 let 과 const 변수를 관리하는 글로벌 스코프가 있다고 말할 수 있습니다.var 변수를 관리하는 글로벌 스코프를 브라우저 환경에서는 window 객체가 관리하는 것입니다. 즉, window 객체의 속성이 됩니다.let 과 const 변수를 관리하는 글로벌 스코프는 ES6에 도입된 것으로 Script 스코프라고도 합니다. 즉, window 객체의 속성이 되지 않습니다.그리고 ES6 의 모듈 스코프가 있습니다. () 로 만들수 있고 글로벌 스코프를 오염시키지 않는 모듈만의 독립 스코프가 만들어 집니다.전역 스코프 (Global Scope) ├── var 변수 (전역 객체의 속성으로 등록) │ └── window.variableName으로 접근 가능 ├── let, const 변수 (전역 객체의 속성이 아님) => Script 스코프 │ └── window.variableName으로 접근 불가 └── 모듈 스코프 (Module Scope) └── 전역 스코프와 분리된 독립적인 스코프그림으로 나타내면 아래와 같습니다.(사진)자 이쯤에서 글로벌 스코프가 무엇일까요? 어떤 성격을 가지고 있는 것일까? 를 이해하는 것이 중요합니다.글로벌 스코프에 선언한 변수는 블록이나 함수 블록에 동일한 이름의 변수가 없을 때, 어느 함수나 블럭에서 참조할 수 있다는 것을 의미합니다.예제를 들면 아래와 같습니다.// Global Scope (Window Object) var globalVar = "I'm a global variable"; // Script Scope let scriptLet = "I'm a script-scoped variable"; const scriptConst = "I'm a script-scoped constant"; function outerFunction() { // Outer Function Scope let outerVar = "I'm in the outer function"; function innerFunction() { // Inner Function Scope let innerVar = "I'm in the inner function"; { // Block Scope :: 여기 let blockVar = "I'm block-scoped"; const blockConst = "I'm a block-scoped constant"; console.log(blockVar); // 접근가능 console.log(innerVar); // 접근가능 console.log(outerVar); // 접근가능 console.log(scriptLet); // 접근가능 console.log(globalVar); // 접근가능 } // 접근할 수 없습니다. // console.log(blockVar); } innerFunction(); } outerFunction(); console.log(globalVar); console.log(scriptLet); 그렇다면 어떻게 Block Scope :: 여기 에서 globalVar 변수를 접근할 수 있는 것일까요?바로 스코프 체인을 하기 때문입니다. 자바스크립트는 변수를 사용할 때, 해당 변수를 먼저 찾아서 참조해야 합니다.그래야 변수의 값을 읽거나 변수에 값을 쓸 수 있기 때문입니다.globarVar 는 어느 깊이에 있는 블럭(함수 블럭 포함)이더라도 자신을 포함하여 상위 블럭에 동일한 이름의 변수가 없는한 접근할 수 있습니다.마치 우리가 누구나 아는 스타를 글로벌 스타라고 부르는 것처럼 globarVar 는 어느 블럭에서나 참조할 수 있죠.그렇게 되는 이유는 스코프체인의 순서가 로컬 블럭 스코프부터 찾고 제일 나중에 글로벌 스코프를 찾기 때문입니다. 로컬 스코프를 찾아서 없으면 -> 상위 스코프에서 찾는다 -> 그래도 없으면 다시 상위 스코프에 가서 찾는다 -> ... -> Script 스코프에서 찾는다 -> Window 객체가 관리하는 Global 스코프에서 찾는다.위 순서에서 Script 스코프 또한 제일 끝부분에서 검색하기 때문에 일종의 글로벌 스코프가 되는 것입니다.그림으로 그려보면 아래와 같습니다.(사진)좀 더 자세한 내용은 아래 강좌를 보시면 도움이 될 것 같습니다.스코프 체인과 참조 오류(Scope Chaining and Reference Error)그리고 스코프 체인과 프로토타입 체인을 혼동하실 수 있어서 프로토타입 체인 영상도 같이 보시면 좋을 것 같습니다.프로토타입 체인 답변이 팀오님에게 도움 드렸기를 바랍니다. 감사합니다 😊
질문&답변
keys(), entrieS() 같은 함수의 반환값이 왜 iterator인지 잘 이해가 안갑니다..!
팀오님 안녕하세요! 질문 주셔서 감사합니다! 😊배열의 keys(), values(), entires() 는 모두 array iterator 를 반환합니다. 그래서 MDN 의 공식 문서에 아래와 같이 설명 되어 있습니다. (keys() 만 링크해 놓을게요!)The keys() method of Array instances returns a new array iterator object that contains the keys for each index in the array.코드로 직접 확인해 보겠습니다! 배열을 정의하고 values() 반환값을 확인해 보겠습니다.(사진)그러면 위 그림처럼 Array Iterator 를 반환하고 Array Iterator 의 프로토타입에 next 와 같은 iterable 프로토콜을 정의하고 있는 것을 알 수 있습니다.자바스크립트에서 모든 배열은 iterable 객체인데요 그 이유는 바로 [Symbol.iterator]() 를 정의하고 있기 때문입니다.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Symbol.iterator그래서 자바스크립트 코드를 작성할 때 많이 사용하는 Object 의 keys, values, entries 메서드는 배열을 반환하고 그 배열들이 모두 iterable 프로토콜을 준수하고 있는 배열 객체이기 때문에 for ... of 와 같은 이터러블 순회 루프를 사용할 수 있는 것입니다. 그래서 아래와 같이 확인할 수 있습니다.(사진)답변이 팀오님의 궁금증에 도움이 되길 바랍니다. 😊 평일에는 제가 답변을 조금 늦게 드릴 수 있는 점 양해 부탁드리겠습니다 🙇♂
질문&답변
var 변수의 문제점 설명하실 때 질문 있습니다.
안녕하세요, 산성님! 질문 주셔서 감사합니다. 함수 스코프와 블록 스코프에서 같은 이름의 변수를 사용했을 때, 어떻게 메모리가 할당되는지를 질문하신 것 같아요. 예시 코드인 testShadowing 함수 안에서 let x = 5;로 변수 x를 선언했고 if 블록 안에서 let x = 10;으로 또 다시 변수 x를 선언했습니다.이때 두 개의 x 변수는 각각 독립적으로 서로 다른 메모리 공간에 저장된답니다. function testShadowing() { let x = 5; if (true) { let x = 10; console.log(x); } console.log(x); } testShadowing() 함수가 실행되면, 자바스크립트 엔진은 다음 순서로 동작합니다: 함수가 호출되면 실행 컨텍스트라는 특별한 공간이 만들어져요. 실행 컨텍스트 안에는 변수를 저장할 수 있는 환경이 마련되는데, 이걸 변수 환경이라고 합니다.함수 안에 있는 변수들을 위한 공간이 변수 환경에 미리 만들어지는데요 var와 let, const 에 따라 초기값이 조금 다릅니다.이때 let이나 const로 선언된 변수들은 uninitialized라는 상태가 됩니다.반면에 var로 선언된 변수들은 undefined라는 값으로 초기화되죠함수 코드가 한 줄씩 실행되면서 변수에 값이 할당되기 시작합니다.let이나 const로 선언된 변수들은 선언문이 실행되기 전까지는 사용할 수 없어요. 그래서 이 기간을 일시적 사각지대(Temporal Dead Zone, TDZ)라고 합니다.선언문이 실행되면 비로소 변수에 값이 할당되고, 변수를 사용할 수 있게 되는 것이죠. testShadowing 코드에 위 단계를 대입해 보면: testShadowing 함수가 호출되면 실행 컨텍스트가 만들어지고, 변수 x를 위한 공간이 만들어집니다.let x = 5;가 실행되면서 변수 x에 값 5가 할당되죠if 블록 안에서 let x = 10;이 실행되면, 새로운 블록 스코프가 만들어지고 그 안에 또 다른 변수 x가 생겨요. 이 x는 블록 바깥에 있는 x와는 다른 변수입니다.블록 안에서 console.log(x);가 실행되면, 블록 안에 있는 x의 값인 10이 출력됩니다.블록이 끝나면 블록 안에서 만들어진 x는 사라지게 됩니다. 즉 더 이상 접근할 수 없게 되는 것이죠.함수 마지막에 있는 console.log(x);가 실행되면, 함수 바깥에 있는 x의 값인 5가 출력됩니다. 아래는 testShadowing 을 실행했을 때 스코프 체인의 모습니다. Block 스코프는 if 문 블럭 스코프를 Local 스코프는 testShadowing 함수 스코프를 나타냅니다. let 으로 x 변수를 선언 및 할당 했기 때문에 각 스코프마다 x 변수가 존재하는 것을 알 수 있습니다.(사진)이렇게 let과 const 는 var 달리 블록 레벨 스코프를 갖기 때문에 서로 다른 스코프에서 같은 이름을 가진 변수를 여럿 선언하더라도 서로 다른 변수로 취급된다는 걸 알 수 있습니다. 이름이 같아서 하위 스코프의 변수가 상위 스코프의 변수를 가리는 이런 현상을 변수 쉐도잉이라고 합니다.변수 쉐도잉이 발생하는 이유는 변수를 사용하려 할 때, 스코프 체인을 통해서 변수를 찾게 되는데 현재 실행 중인 코드에서 가장 가까운 스코프부터 찾기 때문입니다. 정리하면, 함수가 실행될 때 변수를 위한 공간은 미리 마련되지만, 실제로 변수에 값이 할당되는 건 해당 변수 선언문이 실행되는 시점이에요. 특히 let이나 const로 선언한 변수는 선언 전에 사용하려고 하면 에러가 발생하니 주의해야 합니다. 아래는 관련 수업의 링크입니다. 디버거를 같이 실행하면서 함수 실행 컨텍스트 및 스코프 체인을 설명하고 있어요. 참고하시면 좋을 것 같습니다. - 함수 실행 컨텍스트 2편 - 다시 보는 함수 스코프와 블록 스코프- https://www.inflearn.com/course/lecture?courseSlug=%EC%A7%84%EC%A7%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EC%B4%88%EB%B6%80%ED%84%B0-%EA%B3%A0%EA%B8%89%EA%B9%8C%EC%A7%80&unitId=176250- 스코프 체인과 참조 오류- https://www.inflearn.com/course/lecture?courseSlug=%EC%A7%84%EC%A7%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EC%B4%88%EB%B6%80%ED%84%B0-%EA%B3%A0%EA%B8%89%EA%B9%8C%EC%A7%80&unitId=177158