Scope

feelslikemmmm·2020년 9월 18일
0

javascript

목록 보기
19/37
post-thumbnail

► Q1: greetSomeone() 과 firstName 실행 결과는?

let greeting = 'Hello';
function greetSomeone() {
	let firstName = 'Josh';
	return greeting + ' ' + firstName;
}
greetSomeone(); // hello Josh;
firstName; // firstName is not defined (ReferenceError)

► 변수 firstName에 접근할 수 있는 범위가 존재합니다.

  • Local Scope 안쪽에서 선언된 변수는 밖에서 사용할 수 없습니다.
    let greeting = 'Hello'; //이 구간부터 Global Scope
    function greetSomeone() { // 이 구간부터 } 까지 local Scope
    	let firstName = 'Josh';
    	return greeting + ' ' + firstName;
    }

► Scope : 변수 접근 규칙에 따른 유효 범위

  • 변수는 어떠한 환경 내에서만 사용 가능하며, 프로그래밍 언어는 각각의 변수 접근 규칙을 갖고 있습니다
  • 변수와 그 값이, 어디서부터 어디까지 유효한지를 판단하는 범위
  • JavaScript는 기본적으로, 함수가 선언되는(lexical) 동시에 자신만의 Scope를 가집니다.

► Rule 1 : Local Scope vs Global Scope

let greeting = 'Hello'; //이 구간부터 Global Scope
function greetSomeone() { // 이 구간부터 } 까지 local Scope
	let firstName = 'Josh';
	return greeting + ' ' + firstName;
}
  • 안쪽 Scope에서 바깥 변수/함수를 접근하는 것은 가능
  • 바깥쪽 Scope에서 안쪽/변수를 접근하는 것은 불가능
  • Scope는 중첩이 가능합니다.
    • 함수 안에 함수를 넣을 수 있습니다.
  • Global Scope는 최상단의 Scope로, 전역 변수는 어디서든 접근이 가능합니다.
  • 지역 변수는 함수 내에서 전역 변수보다 더 높은 우선순위를 가집니다.

► 문제 1

let name = "Richard";

function showName() {
  let name = "Jack"; // 지역 변수
  // showName 함수 안에서만 접근 가능
  console.log(name); // ???
}

console.log(name); // ???
showName();
console.log(name); // ???

위 코드에서 순서대로 콘솔에 출력되는 결과는?

1. Richard / Jack / Jack

2. Richard / Jack / Richard

3. Jack / Richard / Richard

4. Jack / Jack / Jack

정답 ) 2

► 문제 2

let name = "Richard";

function showName() {
  name = "Jack"; // 전역 변수
  // 선언(let)이 없기 때문에, 바깥 scope에 있는 name이라는 변수를 가져옵니다
  console.log(name); // ???
}

console.log(name); // ???
showName();
console.log(name); // ???

위 코드에서 순서대로 콘솔에 출력되는 결과는?

1번 Richard / Jack / Jack

2번 Richard / Jack / Richard

3번 Jack / Richard / Richard

4번 Jack / Jack / Jack

정답) 1

► Rule 2 : Function Scope vs Block Scope

  • Block : 중괄호로 시작하고, 끝나는 단위


► 문제 1

콘솔에 출력되는 결과는?

for (let i = 0; i < 5; i++) {
	console.log(i); // 다섯번 iteration
}
console.log(`final i: ${i}`);

정답 ) // Uncaught ReferenceError: i is not defined
      // Block 범위를 벗어난 즉시 변수를 사용할 수 없기 때문입니다.

► var 키워드 vs let 키워드

  • 변수를 정의하는 또 다른 키워드 var
    • JavaScript는 기본적으로, 함수단위로 자신만의 Scope를 가집니다. → var 키워드(old way)
    • 그러나 Block 단위로 Scope를 구분했을 때에 예측하기 쉬운 코드를 작성할 수 있습니다 → let 키워드

► 문제

콘솔에 출력되는 결과는?
for (var i = 0; i < 5; i++) {
	console.log(i); // 다섯번 iteration
}
console.log(`final i : ${i}`);

정답) 5 // var을 썼기 때문에 Block을 벗어나도 (같은 function scope)에서는 사용이 가능

► const 키워드

  • 값이 변하지 않는 변수, 즉 상수를 정의할 때 사용하는 키워드 const
  • let 키워드와 동일하게 Block Scope를 따릅니다
  • 값을 재정의 하려고 하면 TypeError를 냅니다


► 요약

► var를 사용한 재선언시, 아무런 에러도 내지 않습니다

let myName = 'Steve';
let myName = 'John';
//error 발생
var yourName = 'Tony';
var yourName = 'Tim';
//에러가 발생하지 않음

실제 코딩할 때에 재선언을 해야 할 필요가 있을까요?
보통 이 경우는 버그이며, let 키워드가 이러한 실수를 막아줍니다

► Rule 3 : 전역 변수와 window 객체

  • 전역 범위를 대표하는 객체 window
  • Global Scope에서 선언된 함수, 그리고 var 키워드를 이용해 선언된 변수는 window 객체와 연결

  • ⚠️전역 범위에 너무 많은 변수를 선언하지 않도록 주의해야 합니다

► Rule 4 : 선언 없이 초기화된 전역 변수

  • ❗️절대로, 선언 키워드 (var, let, cost) 없이 변수를 초기화 하면 안됩니다!
이 경우에 에러를 내주면 좋겠지만 에러가 나지 않습니다

function showAge() {
	//age는 전역 변수로 취급됩니다
	age = 90;
	console.log(age);
}
showAge(); // 90
console.log(age); // 90

► 위와 같은 실수를 방지하고 싶을 경우, Strict Mode를 사용하세요

'use strict';
//use strict를 정의해준 후 같은 코드를 작성하면 RefenceError가 발생합니다
function showAge() {
	//age는 전역 변수로 취급됩니다
	age = 90; //❗️RefenceError
	console.log(age);
}
showAge(); // 90
console.log(age); // 90

► 문제 1

  • 다음 중 맞는 설명을 모두 고르세요
  1. let이 var보다 좋은 이유 중 하나는, 재선언을 방지해주기 때문이다.
  2. let은 function 단위로 유효범위를 가진다
  3. scope는 변수 접근 규칙이다
  4. 기본적으로 자바스크립트는 block 단위의 scope 규칙을 따른다.

정답 ) 3, 4


► 문제 2

  • 다음 중 맞는 설명을 모두 고르세요
  1. 변수를 접근할 수 없을 때 나는 에러는 ReferenceError이다
  2. var로 정의된 전역변수는 window 객체에 담긴다
  3. 변수 선언을 하지 않으면, 어떤 scope에서든 전역변수가 되므로 위험하다. (non-strict mode)

정답) 1, 2, 3

profile
꾸준함을 잃지 말자는 모토를 가지고 개발하고 있습니다 :)

0개의 댓글