Javascript | 스코프

권기현·2020년 5월 31일
0

JavaScript

목록 보기
1/7
post-thumbnail

프론트엔드 개발에 대한 공부를 시작하고 자바스크립트를 계속 만져왔지만, 그 원리, 구동방식, 개념 등에 대해서는 시간을 내어서 공부하지 않았던 것 같다. 면접을 준비하거나 데이터를 프론트 단에서 조작하거나 할 때에 자바스크립트를 깊게 공부해야하는 필요성을 느껴서 앞으로는 다른 기술이 아닌 "자바스크립트"에 대한 내용을 포스팅 해볼까 한다.

클로저를 설명하기 위해 알아야 할 내용 :
전역/지역 scope,
lexical scoping,
Garbage Collector


스코프(Scope)

자바스크립트에서 스코프란 어떤 변수들에 접근할 수 있는지를 정의합니다.

두가지 종류의 스코프

  • 전역 스코프(global scope)
  • 지역 스코프(local scope)

전역 스코프(Global Scope)

변수가 함수 바깥이나 중괄호 ({}) 바깥에 선언되었다면, 전역 스코프에 정의된다고 합니다.
이 설명은 웹 브라우저의 자바스크립트에만 유효합니다.
(Node.js에서는 전역 스코프를 다르게 정의 )

const globalVariable = 'some value'

전역 변수를 선언하면, 파일 내 코드의 모든 곳(함수 포함)에서 해당 변수를 사용할 수 있습니다.

const hello = 'Hi'

const sayHello = () => {
  console.log(hello)
}

console.log(hello) // 'Hi'
sayHello() // 'Hi'

비록 전역 스코프에 변수를 선언할 수는 있어도, 그러지 않는 것이 좋다.
왜냐하면, 두 개 이상의 변수의 이름이 충돌하는 경우가 생길 수도 있기 때문이다.
만약 변수를 const나 let을 사용하여 선언했다면, 이름에 충돌이 발생할 때마다 에러가 발생합니다.

// 이렇게 작성하여서는 안된다.
let thing = 'something'
let thing = 'something else' // Error, thing has already been declared

만약 var를 이용하여 변수를 선언했다면, 두 번째 변수가 첫 번째 변수를 덮어쓰게 된다.
이렇게 사용하게 된다면 디버깅이 어려워지기 때문에 이런 식으로 사용하면 안 됩니다.

// 이렇게 작성하여서는 안된다.
var thing = 'something'
var thing = 'something else' 

console.log(thing) // ‘something else’

그래서 특별한 이유가 아니라면 전역 변수가 아닌, 지역 변수로써 변수를 선언해야 한다.

지역 스코프 (Local Scope)

코드의 특정 부분에서만 사용할 수 있는 변수는 지역 스코프에 있다고 할 수 있다. 이런 변수들은 지역 변수라고 불린다.

자바스크립트에서는 두 가지의 지역 변수

  • 함수 스코프(function scope)
  • 블록 스코프(block scope)

함수 스코프(Function Scope)

함수 내부에서 변수를 선언하면, 그 변수는 선언한 변수 내부에서만 접근할 수 있습니다. 함수 바깥에서는 해당 변수에 접근할 수 없다.

아래의 예제를 살펴보면 "변수 hello" 는 "sayHello"의 스코프 내에 존재한다는 것을 알 수 있습니다.

const sayHello = () => {
  const hello = 'Hi'
  console.log(hello)
}

sayHello() // 'Hi'
console.log(hello) // Error, hello is not defined

블록 스코프(Block Scope)

중괄호({}) 내부에서 const 또는 let으로 변수를 선언하면, 그 변수들은 중괄호 블록 내부에서만 접근할 수 있습니다.

다음 예제에서 볼 수 있듯이 변수 hello는 중괄호 내부의 스코프에 존재합니다.

{
  const hello = 'Hi'
  console.log(hello) // 'Hi'
}

console.log(hello) // Error, hello is not defined

함수 호이스팅(Function hoisting)과 스코프

함수가 함수 선언식(function declaration)으로 선언되면, 현재 스코프의 최상단으로 호이스팅(hoist) 된다.

- 호이스팅(Hoisting)이란?
: global에 선언된 변수 또는 함수를 최상의 Scope로 끌어올리는 것

개념: 끌어올림. 자바스크립트 엔진이 script 태그를 만나면 자바스크립트 파일을 먼저 쭉 읽으면서 선언된 변수와 함수를 메모리에 저장한다. 이 과정이 끝나면 코드가 위에서 부터 차례대로 실행된다.
즉 코드에서 함수나 변수를 코드의 하단부에 선언했다고 하더라도 코드의 상단부에서 함수를 호출(실행) 할 수 있는 JavaScript 만의 특징이다.

- 함수선언식과 함수표현식

  • 함수선언식(Function Declaration)
    • funtion 함수이름(매개변수){로직} 형태
    • 함수를 선언하여서 쓰는 형태
    • 자바스크립트 인터프리터가 스크립트가 불러오는 시점에 바로 함수를 저장한다.
    • 스크립트가 불러오는 시점에 저장되므로 호이스팅이 발생한다.
    • 함수이름(매개변수) 로 호출해주어야 실행이 된다.
  • 함수표현식(Function Expressions)
    • var 변수이름 = funtion 함수이름(매개변수){로직} 형태
    • 함수를 변수에 답아서 표현한 형태
    • Function Literal(함수 리터럴)로 실행가능한 코드로 해석되어지거나 데이터구조로 할당되어진다.
    • 호출을 따로 하지않아도 바로 해석과 동시에 실행된다.(자가호출함수)
    • 호이스팅이 불가능하다.

함수선언으로 된 구문은 자바스크립트엔진이 바로 해석하여 최상위로 끌어올려진다.
함수표현으로 된 구문은 런타임과정을 가지기 때문에 hoisting되지 않는다.

함수선언식과 표현식 그리고 호이스팅

>함수선언식

function func(){
	function inner(){
		console.log('hello')
	}
	return inner()
	function  inner(){
		console.log('bye')
	}
}

함수선언식으로만 구성되어진 이 소스에서는 "inner()" 이 반환(return inner())되면 항상 "bye"만 찍히는 모습을 볼 수가 있다.
그리고 return inner() 을 어디로 놔두어도 똑같이 bye만 찍히며 함수선언식 의 특징인 호이스팅 의 모습을 보여주고 있다.

>함수표현식

function func(){
	var inner = function(){
		console.log('hello')
	}
	return inner()
	var inner = function (){
		console.log('bye')
	}
}

함수표현식으로 구성되어진 이 소스는 return inner() 이 반환되면 항사 hello만 찍히는 모습을 볼 수가 있다.
그리고 return inner() 을 var inner 위치에 따라서 다른 내용을 보여준다.


아래의 예제에서 두 가지 경우는 같은 결과를 보입니다.

// This is the same as the one below
sayHello()
function sayHello () {
  console.log('Hi')
}
// This is the same as the code above
function sayHello () {
  console.log('Hi')
}
sayHello()

반면 함수가 함수 표현식(function expression)으로 선언되면, 함수는 현재 스코프의 최상단으로 호이스팅되지 않는다.

sayHello() // Error, sayHello is not defined
const sayHello = function () {
  console.log("hi")
}

이렇게 두 방식의 행동이 다르기 때문에, 함수 호이스팅은 혼란스러울 수 있으므로 사용하면 안 됩니다. 언제나, 함수를 호출하기 전에 선언해놓아야 합니다.

함수는 서로의 스코프에 접근할 수 없다.

함수들이 각각 선언되었을 때, 서로의 스코프에는 접근할 수 없다. 어떤 함수가 다른 함수에서 사용되더라도 그렇다.

아래의 예제에서, 함수 second는 변수 firstFunctionVariable에 접근할 수 없습니다.

function first () {
  const firstFunctionVariable = 'I’m part of first'
}
function second () {
  first()
  console.log(firstFunctionVariable) // Error, firstFunctionVariable is not defined
}
profile
함께 일하고 싶은 개발자를 목표로 매일을 노력하고, 옷을 좋아하는 권기현 입니다.

0개의 댓글