Replies: 6 comments 5 replies
-
공유하고싶은 자료 & 개인적으로 정리한 블로그 등이 있다면 여기👇👇👇에 댓글로 공유해주세요 😆 |
Beta Was this translation helpful? Give feedback.
-
스코프Scope를 우리말로 번역하면 ‘범위’라는 뜻을 가지고 있습니다. 즉, 스코프(Scope)란 ‘변수에 접근할 수 있는 범위’라고 할 수 있는데요. 전역스코프와 지역스코프자바스크립트에선 스코프는 2가지 타입이 있습니다. 바로 global(전역)과 local(지역) 인데요. var a = 1; // 전역 스코프
function print() { // 지역(함수) 스코프
var a = 111;
console.log(a);
}
print();
console.log(a); // 111 출처 : https://medium.com/@yeon22/javascript-%EC%8A%A4%EC%BD%94%ED%94%84-scope-%EB%9E%80-bc761cba1023 var, le, const자바스크립트에서 변수(식별자)를 선언하는 방식은 세 가지 var, let, const가 있다. var은 함수 스코프를 따르며 이 말은 즉슨 자신이 선언된 곳과 가장 가까운 함수를 유효 범위로 가진다는 의미이다. let과 const는 블록 스코프를 따르는데, 자신이 선언된 곳과 가장 가까운 블록을 유효 범위로 가진다. var x = 0;
{
var x = 1;
console.log(x); // 1
}
console.log(x); // 1 var은 함수 스코프를 따르기 때문에 첫 번째로 선언된 x와 두 번째로 선언된 x 모두 메인 함수의 전역 공간에 선언되어 있는 것 이다. 두 번째로 선언된 x가 값을 덮어 씌운 것. 그 외에도 var은 재선언과 재할당이 모두 가능, let은 재할당만 가능, const는 재선언과 재할당이 모두 불가능하다. var은 ES6 등장 이후 더이상 쓰지 않으며 변수에 저장된 값이 변경되는 값이라면 let을, 저장만하고 사용하는 값이라면 const를 이용해 선언한다. 스코프 체인자바스크립트 엔진은 식별자를 찾을 때 일단 자신이 속한 스코프에서 찾고 그 스코프에 식별자가 없으면 상위 스코프에서 다시 찾아 나간다. 이 현상을 스코프 체인 이라고 하며 스코프가 중첩되어있는 모든 상황에서 발생한다. 렉시컬 스코프var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // ?
bar(); // ? 렉시컬 스코프는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정된다. 자바스크립트는 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다. 함수를 어디에서 호출하였는지는 스코프 결정에 아무런 의미를 주지 않는다. 위 예제의 함수 bar는 전역에 선언되었다. 따라서 함수 bar의 상위 스코프는 전역 스코프이고 위 예제는 전역 변수 x의 값 1을 두번 출력한다. 호이스팅자바스크립트 엔진은 코드를 인터프리팅 하기 전에 그 코드를 먼저 컴파일한다. var a = 2;를 하나의 구문으로 생각할 수도 있지만, 자바스크립트는 다음 두 개의 구문으로 분리하여 본다. var a; 클로저클로저를 현대 프로그래밍에서 다음과 같이 해석하여 정의할 수 있을것 같다.
함수를 둘러싼 환경이라는 것이 바로 앞에서 설명했던 렉시컬 스코프이다. 함수를 만들고 그 함수 내부의 코드가 탐색하는 스코프를 함수 생성 당시의 렉시컬 스코프로 고정하면 바로 클로저가 되는 것이다. 이제 이 클로저가 자바스크립트에 어떻게 녹아 들어갔는지 살펴보도록 하자. 자바스크립트에서 클로저는 함수가 생성되는 시점에 생성된다. 다음 예시들을 통해서 클로저를 조금 더 정확하게 파악할 수 있다. function foo() {
var color = 'blue';
function bar() {
console.log(color);
}
bar();
}
foo(); bar함수는 우리가 부르는 클로저일까 아닐까? 일단 bar는 foo안에 속하기 때문에 foo스코프를 외부 스코프(outer lexical environment) 참조로 저장한다. 그리고 bar는 자신의 렉시컬 스코프 체인을 통해 foo의 color를 정확히 참조할 것이다. 그럼 클로저라 볼 수 있지 않을까? 아니다. 우리가 부르는 클로저라고 하기에는 약간 거리가 있다. bar는 foo안에서 정의되고 실행되었을 뿐, foo밖으로 나오지 않았기 때문에 클로저라고 부르지 않는다. 대신, 다음 코드는 우리가 실제로 부르는 클로저를 나타내고 있다. var color = 'red';
function foo() {
var color = 'blue'; // 2
function bar() {
console.log(color); // 1
}
return bar;
}
var baz = foo(); // 3
baz(); // 4
이게 바로 클로저다. 그냥 단순하게 보면 "이 당연하게 왜?"라고 생각할 수 있지만, 조금 더 자세히 따져보도록 하자. 일단 중요한 부분은 2~4번, 그리고 7번이다. bar는 자신이 생성된 렉시컬 스코프에서 벗어나 global에서 baz라는 이름으로 호출이 되었고, 스코프 탐색은 현재 실행 스택과 관련 없는 foo를 거쳐 갔다. baz를 bar로 초기화할 때는 이미 bar의 outer lexical environment를 foo로 결정한 이후이다. 때문에, bar의 생성과 직접적인 관련이 없는 global에서 아무리 호출하더라도 여전히 foo에서 color를 찾는 것이다. 이런 bar(또는 baz)와 같은 함수를 우리는 클로저라고 부른다. |
Beta Was this translation helpful? Give feedback.
-
자바스크립트에서 Scope 특징스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 자바스크립트에는 다음 두 가지 스코프가 존재한다.
var a = 4; // 전역 스코프
function print() { // 지역(함수) 스코프
var a = 42;
console.log(a);
}
print(); // 42
console.log(a); // 4 대부분의 C-family language는 블록 레벨 스코프(block-level scope)를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다. ( ECMAScript 6에서 도입된 let, const keyword를 사용하면 블록 레벨 스코프를 사용할 수 있다. ) Global Scopevar 키워드로 선언한 전역 변수는 전역 객체(Global Object) window의 프로퍼티이다. Lexical Scope프로그래밍 언어는 두 가지 방식으로 함수의 상위 스코프를 결정한다.
자바스크립트를 비롯한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따른다. var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1 Scope도 엄청 많이 생기면 메모리 오버플로우가 발생할까요?Scope도 객체이므로 많이 중첩된다면 오버플로우가 발생 할 수 있습니다. |
Beta Was this translation helpful? Give feedback.
-
1. 클로저란 무엇이며, 어떤 경우에 유용하게 쓰일 수 있나요?클로저는 바깥의 변수를 끌어다 쓰는 것입니다. 상위 함수가 하위 함수를 리턴하고, 하위 함수가 상위 함수 스코프 내의 변수를 참조하고 있다면 상위함수의 실행이 끝나더라도 상위 함수의 변수들이 메모리 상에 사라지지 않고 그대로 남있습니다. 이때 중요한 점은, 단순히 하위 함수에서 참조되는 변수만이 사라지는 것이 아니라 상위 함수 스코프 내에서 선언된 모든 변수와 함수들이 남아 있을 것이라는 점입니다. 이러한 클로저는 currying 기법의 근간이 되는 개념입니다. 2. 클로저를 바탕으로 자바스크립트 currying 기법을 설명해주세요.currying 을 통해 함수를 만들면, 하위 함수가 상위 함수의 매개변수에 그대로 접근할 수 있기 때문에, 매개변수에 따라 조금씩 다른 일을 하는 함수들을 단계적으로 만들어나갈 수 있습니다. 특히 이러한 currying 함수를 콜백으로 사용할 경우, 해당 콜백을 받은 함수가 이 currying 함수를 자유 자재로 다룰 수 있어 프로그램의 유연성이 더 높아질 수 있습니다.
const sum = function (a, b) {
return function (b) {
return a + b;
}
}
const sum10 = sum(10);
sum10(20); // 30
sum(10)(20); // 30 |
Beta Was this translation helpful? Give feedback.
-
1. 전역 변수를 전역 스코프 또는 전역 네임스페이스에 선언하여 사용하는게 왜 안티패턴 일까요?
다음과 같은 문제를 해결하기위해 '모듈' 시스템이 생겼습니다. 저희가 사용한 https://ko.javascript.info/modules-intro const와 let이 존재하지 않을 때, var으로만 변수를 선언 할 수 있었을때, 'AMD', 'CommonJS', 'UMD'와 같은 모듈 라이브러리가 등장했고 이후 ES6에서 표준 문법으로 자리잡았습니다. 2. '자바스크립트는 함수 레벨 스코프(function-level scope) 를 따른다.' 고 했는데 let, const같이
|
Beta Was this translation helpful? Give feedback.
-
아래 결과를 예측해보자. let count = 0;
for (var i=0; i<42; i++) {
for (var i=0; i<42; i++) {
count++;
}
}
console.log(count); count는 42가 나온다. 그 이유는 i 가 var로 선언돼서 전역스코프로 선언됐기 때문이다. for 조건에서는 항상 let을 사용해주자. let count = 0;
for (let i=0; i<42; i++){
for (let i=0; i<42; i++) {
count++;
}
}
console.log(count); //1764 |
Beta Was this translation helpful? Give feedback.
-
주제 키워드는
✨Scope✨
입니다.
☘️ 하위 주제 키워드
⏳스레드에 각 페어당 소요시간 적어주세요!
(ex) holee 90분 소요
Beta Was this translation helpful? Give feedback.
All reactions