게시글
질문&답변
2024.10.18
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)그리고 스코프 체인과 프로토타입 체인을 혼동하실 수 있어서 프로토타입 체인 영상도 같이 보시면 좋을 것 같습니다.프로토타입 체인 답변이 팀오님에게 도움 드렸기를 바랍니다. 감사합니다 😊
- 0
- 2
- 46
질문&답변
2024.09.06
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 와 같은 이터러블 순회 루프를 사용할 수 있는 것입니다. 그래서 아래와 같이 확인할 수 있습니다.(사진)답변이 팀오님의 궁금증에 도움이 되길 바랍니다. 😊 평일에는 제가 답변을 조금 늦게 드릴 수 있는 점 양해 부탁드리겠습니다 🙇♂
- 0
- 1
- 54
질문&답변
2024.04.19
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
- 0
- 2
- 275
질문&답변
2024.03.12
메모리에 변수 생성과 값을 할당할 때
안녕하세요 강동하님! 질문 주셔서 감사합니다. 변수에 할당 되는 값의 메모리처리 관련해서 질문을 주신 것 같아요.자바스크립트는 변수에 값을 할당할 때마다 런타임에 메모리에 생성되고 관리(가비지 컬렉션) 됩니다예를 들면, let number = 5; 코드가 있을 때 JavaScript 는 메모리에서 5를 저장할 공간을 할당하고, 해당 공간(메모리 셀) 에 값을 5를 쓰고 number라는 이름으로 이 공간을 주소를 통해 참조하게 합니다.이것이 대원칙이지만 최적화 이유로 정수와 객체등 다르게 처리하는 부분이 있습니다. 이와 관련 내용은 “섹션 14. V8 자바스크립트 엔진” 에 자세히 다루고 있어 참고하시면 좋을 것 같습니다.감사합니다😊
- 0
- 2
- 248
질문&답변
2024.01.06
클로저 스코프와 블록 스코프 질문드립니다.
튜브님 안녕하세요! 질문 주셔서 감사합니다. 아주 중요한 내용을 담고 있는 질문이라고 생각합니다. count 변수가 기본값 매개변수를 사용할 때, 왜 다른 스코프에 위치하는지 알아볼게요. 기본값 매개변수는 ES6에 도입되었는데요 MDN의 문서에 따르면(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) 아래와 같이 적혀 있습니다. "The default parameter initializers live in their own scope, which is a parent of the scope created for the function body."즉, 함수가 기본값 매개변수를 사용하면 기본값 매개변수 초기자는 함수 body 스코프의 부모가 되는 자체 스코프를 갖는다라고 합니다. 예를 들어, const test1 = (value) => { let count = value; debugger; } test1(10);위 test1 함수는 기본값 매개변수를 사용하지 않기 때문에 함수 body 가(함수 스코프) 최상위 스코프가 됩니다. (사진)그래서 위 그림처럼 count 와 value가 모두 함수의 local 스코프에 존재하게 됩니다. 그런데 아래와 같이 기본값 매개변수를 사용하면 얘기가 달라집니다. const test2 = (value = 10) => { let count = value; debugger; } test2();(사진)기본값을 갖는 value는 함수 body 의 부모 스코프에서 초기화가 되고 그걸로 값을 초기화하는 count 변수는 local이 아닌 block 스코프에 존재하게 됩니다.사실 함수에 기본값 매개변수만 있고 그 값을 실제로 사용하지 않아도 함수 body 안에 선언하고 정의한 변수의 스코프가 변경됩니다.const test2 = (value = 10) => { let count = 999; debugger; } test2();또는const test2 = (value = 10) => { var count = 999; debugger; } test2();(사진)(사진)이 내용을 비슷하게 흉내를 내 보면 아래와 같습니다. 억지로 var 변수로 바꾸고 초기화를 다른 블럭에서 해 본 것입니다. (사실 위 내용으로 인해 var count = value 나 let count = value 나 상관 없습니다. 😅)const test3 = (value = 10) => { var count; { count = value; } debugger; } test3();(사진)함수 스코프를 갖도록 var count 를 선언했는데 count 는 그림과 같이 block 스코프에 존재합니다. 기본값 매개변수를 사용했기 때문에 var count 의 스코프가 변경되었기 때문입니다. 이 상태에서 inner 클로저를 정의하고 호출해 보면const test4 = (value = 10) => { var count; { count = value; } const inner = () => { console.log(count); // block debugger; }; inner(); } test4();(사진)그림과 같이 block 스코프에 있는 count 를 사용하게 됩니다. 이 block 스코프는 inner 함수가 도달할 수 있는 상위 스코프이기 때문에 따로 변수를 캡쳐해서 클로저 스코프를 만들지 않습니다.이 것은 아래와 같이 Script 스코프에 있는 변수 a를 inner에서 참조할 때, inner 가 Script 스코프에 도달 할 수 있기 때문에 클로저 스코프를 만들지 않는 이유와 동일합니다.let age = 10; const test5 = (value = 10) => { var count; { count = value; } const inner = () => { console.log(age); // script console.log(count); // block debugger; }; inner(); } test5();(사진)정리해 보면, 아래와 같을 것 같습니다.1. 기본값 매개변수를 사용하면 기본값 매개변수를 초기화하는 스코프가 함수 body 안의 변수 스코프에 영향을 준다.기본값 매개변수를 사용하든 사용하지 않든 함수 안의 변수는 block 스코프에 존재하게 되는데 클로저가 스코프 체인을 통해서 접근할 수 있는 상위 스코프이기 때문에 따로 변수 캡쳐를 위한 클로저 스코프를 만들지 않는다.(사진)정리 그림: 기본값 매개변수 사용할 때 (사진)정리 그림: 기본값 매개변수를 사용하지 않을 때 답변이 도움이 되었기를 바래봅니다. 감사합니다. 🙂
- 2
- 1
- 552
질문&답변
2023.12.05
코드샌드박스 화면구성이 달라졌네요.
안녕하세요. 방종훈님! 방금 코드샌드박스 업데이트 대응 방법을 추가했습니다. 관련 소식은 https://www.inflearn.com/news/1092884 에서 확인 부탁드릴게요!감사합니다.
- 0
- 2
- 417
질문&답변
2023.12.05
코드샌드박스 화면구성이 달라졌네요.
안녕하세요. 방종훈님! 질문 주셔서 감사합니다.코드샌드박스 업데이트로 인해 실습환경이 많이 변경되었네요. 저도 오늘 확인하고 바닐라 자바스크립트 템플릿이 없어서 조금 당황했습니다.수업 구성 방법은 제가 강의를 촬영해서 올려드리도록 하겠습니다.먼저 수업 진행을 위해서 아래 링크의 코드샌드박스를 포크(fork)해서 사용하시면 됩니다.https://codesandbox.io/p/sandbox/realjavascript-7q8jh6 아래는 fork 하는 방법과 콘솔 패널을 여는 방법입니다.(사진)
- 0
- 2
- 417
질문&답변
2023.11.12
커리큘럼 관련 질문
안녕하세요. 질문 주셔서 감사합니다. 기초부분을 좀 더 보강하기 위해서 강의 오픈 후에 수업을 추가하게 되었습니다. 그래서 새로 추가한 섹션이나 강의는 [추가섹션]과 [추가강의]로 표시를 하게 되었습니다. "숫자의 표현과 2진수 비트 연산" 추가섹션은 컴퓨터에서 어떻게 숫자를 2진수로 표현하는지를 다루는 내용인데요. 2진수 내용은 꼭 알아야할 내용이기도 하고 다음 섹션인 문자열의 유니코드를 설명할 때, 유니코드가16진수로 표시되기도 하고 빅엔디안과 리틀엔디안 내용이 나와서 "문자열 메서드와 유니코드" 섹션 앞에 추가하게 되었습니다. 추가섹션을 함수 기본편 다음에 넣은 이유는 함수를 사용해서 예제를 작성하며 설명을 하기 때문에 함수 기본편 섹션 다음에 추가섹션을 편성했습니다. 감사합니다.
- 0
- 1
- 237