자바스크립트의 변수, 함수에는 스코프가 존재한다.

스코프는 자바스크립트에서 어떤 변수들에 접근할 수 있는지를 나타낸다.

 

ES5 까지는 함수 레벨의 스코프(function scope)만 사용 가능했으나,

ES6 부터는 let과 const로 블록 레벨의 스코프(block scope)를 사용할 수 있다.

 

이 스코프에 대해서 알아보자

 

https://www.edwith.org/boostcourse-web/lecture/16693/

 

[LECTURE] 1) 자바스크립트 변수-연산자-타입 : edwith

들어가기 전에 컴파일 단계가 없는 자바스크립트의 type(형)은 실행단계에서 타입이 결정됩니다. 변수선언은 어떻게 정의하고, 자바스크립트의 타입은 어떤 것들이 있는지 확인해봅니다.... - 부스트코스

www.edwith.org


스코프와 레벨

스코프는 다음과 같이 구성된다

  • 전역 스코프
  • 지역 스코프
    • 함수 레벨 스코프
    • 블록 레벨 스코프

앞서 블록 레벨 스코프, 함수 레벨 스코프를 설명했는데 전역 스코프와 지역 스코프는 무엇인가?

 

아래 내용을 보며 살펴보도록 하자

전역 스코프

변수가 함수 바깥이나 {} 바깥 에서 선언되었다면, 전역 스코프에 정의된다.

let a = 'aa'

위의 a는 어디에서나 접근 가능하다.

 

변수를 글로벌 변수로 선언했을 경우, 이는 전역 스코프에 정의된다고 알 수 있다.

 

let a = 'first'
let a = 'second' // 이미 선언되어있음

전역 스코프에서 중복 재할당의 문제가 발생할 수 있으므로 주의해야 한다.

 

지역 스코프

지역 스코프는 특정 영역에서만 사용할 수 있는 변수이다.

지역 스코프는 다음과 같이 2가지로 이루어진다

  • 함수 레벨
  • 블록 레벨

함수 레벨 스코프

function a(){
  var b = 2;
}

위와 같이 선언했을 때, b는 함수 a에서만 사용할 수 있다.

함수 레벨 스코프는, 함수 내에서만 사용 가능한 변수를 의미한다.

 

함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다.

즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

 

블록 레벨 스코프

블록 내부에서 const, let으로 변수를 선언한다면, 이 변수들은 블록 내부에서만 사용이 가능하다.

{
  const a = 'hello world'
  console.log(a) // 'hello world'
}
console.log(a) // Error, a is not defined

모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하다.

따라서 코드 블록 외부에서는 참조할 수 없다.

 

즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.


정리하자면 javascript는 ES5까지는 함수 레벨 스코프만 제공했으나,

ES6부터는 let, const를 이용해 블록 레벨 스코프 선언이 가능하다.

 

const를 먼저 사용하자. 재할당해야 하는 경우가 생기면 let을 사용한다.

 

var는 block scope를 지원하지 않기 때문에 되도록 사용하지 말자

 

앞의 글에서 자바스크립트에는 타입이 다음과 같은 것들이 존재한다고 설명했다.

undefined, null, boolean, number, string, object, function, array, Date, RegExp

 

  • 자바스크립트에서 타입은 선언할 때가 아니고, 실행타임에 결정된다. (실제 그 타입의 변수가 실행되는 경우)
  • 함수 안에서의 파라미터나 변수는 실행될 때 그 타입이 결정된다

위 성질은 자바스크립트가 컴파일을 총 2번 하기 때문에 일어난다.

자세한 컴파일 과정은 다음과 같다.

  1. 함수, 변수들 호이스팅하며 선언한다.
  2. 선언된 객체들에게 값을 할당한다.

몇몇 타입들은 typeof 를 이용해 타입을 검사할 수 있다.

  • undefined : 변수가 정의되지 않거나 값이 없을 때
  • number : 데이터 타입이 수일 때
  • string : 데이터 타입이 문자열일 때
  • boolean : 데이터 타입이 불리언일 때
  • object : 데이터 타입이 함수, 배열 등 객체일 때
  • function : 변수의 값이 함수일 때
  • symbol : 데이터 타입이 심볼일 때

심볼 타입

위 타입들 중 대부분은 이해가 가능하지만, 심볼 타입은 도데체 무엇일까?

 

심볼은 es6에서 추가된 새로운 타입이다.

유일한 객체의 프로퍼티 키(property key)를 만들기 위해 사용한다.

 

key로 사용했을 때, 다른것들과 절대 충돌이 나지 않는 점을 이용한다.

 

ES6의 class에서 private한 객체를 만들 때 사용할 수 있다.

const Count = (() => {
  const count = Symbol('COUNT');
  class Count {
    constructor() {
      this[count] = 0;
    }
    getScore() { return this[count]; }
    setScore(score) { this[count] = score; }
  }
  return Count;
})();

const test = new Count();

위와 같이 선언했을 때, test.count에 접근할 수 없다.

 

하지만 이 방법으로 완전히 private한 요소를 만들 수 있는 것은 아니다.

다음과 같은 방법으로 test.count에 접근할 수 있다.

const testSymbol = Object.getOwnPropertySymbols(test)[0];
test[testSymbol] = 20 // this is count

원시 타입 vs 참조 타입

위 타입을 기본형(원시 타입)참조형(참조 타입)으로 나눌 수 있는데 이는 C언어에서 call by value, call by reference의 차이로 이해하면 쉽다.

 

원시 타입 (Primitive) : call by value

  • Number
  • String
  • Boolean
  • null
  • undefined

참조 타입 (Reference) : call by reference

  • Object
  • Array
  • Function
  • RegExp

두 타입의 차이를 알아보기 위해 다음의 예제를 실행해보자

// 원시 타입의 경우
let a = 3;
let b = a;

b = 2;	// 2
a	// 3

// 참조 타입의 경우
let objA = { value : 3 }
let objB = objA

objB.value = 2;
objA	// {value: 2}

objA는 객체 (Object)타입 이므로 objB = objA 를 수행했을 때, objB는 objA의 주소를 가진다.

 

그렇다면 참조 타입에서 '값 복사'를 하려면 어떻게 해야 할까?? (주소를 복사하지 않음)

 

Object.assign()을 이용한다. (객체의 depth가 1단계만일때)

function cloneObject(obj) { 
  return Object.assign({}, obj); 
}

위 함수의 경우 obj의 depth가 1단계 만이라면, (최대 depth가 1단계) 객체를 값 복사 할 수 있다!

 

다음과 같은 객체의 경우 유효하다.

 

// 자식들이 원시 타입이다.
let obj = {
  child1 : 10,
  child2 : "hello",
  child3 : undefined,
  child4 : null
}

허나 Object.assign의 경우 자식이 참조 타입인 경우 자식에 대한 복사는 다시 참조 복사를 해버리는 문제가 발생한다.

이러한 복사를 얕은 복사 라고 한다.

 

이 경우 다음 방법을 이용한다.

 

JSON.parse() & JSON.stringify()을 이용한다.

JSON.stringify(obj)는 obj의 형태를 문자열로 치환해준다.

let obj = {
  child1 : 10,
  child2 : "hello",
  child3 : undefined,
  child4 : null
}

JSON.stringify(obj) // "{"child1":10,"child2":"hello","child4":null}"

JSON.parse("string")의 경우 "string"을 객체로 복구한다.

let str = JSON.stringify(obj)
JSON.parse(str) // {child1: 10, child2: "hello", child4: null}

두 메소드를 합치면 객체를 깊은 복사 할 수 있다.

허나 이 방법은 매우 느리므로 정말 깊은 복사를 해야 할 때만 이용하도록 하자.

(문자열 치환후 다시 객체로 복구하므로...)

 

함수의 반환 타입은 무엇인가?

function printName(firstname) {
    var myname = "jisu";
    var result = myname + " " +  firstname;
}

위 코드를 실행했을 때, printName의 반환값은 무엇일까?

답은 undefined이다.

 

자바스크립트 함수는 반드시 return값이 존재하며, 없을 때는 기본 반환값인 'undefined'를 반환한다.

 


실제 개발을 해보다 보면, 자바스크립트의 타입 때문에 생기는 에러가 자주 발생한다.

다음 객체를 비동기로 받아 사용한다고 생각해보자.

let res = {
  hello : "world"
}

만약 API에서 res를 제대로 받아온다면 res.hello를 실행했을 때 문제가 없을 것이다.

그러나 res를 제대로 받아오지 못한다면 (res가 undefined)라면 res.hello는 undefined일 것이다.

 

이 경우 res.hello는 원시타입이므로 큰 문제가 발생하지 않을 수 있지만 함수등의 경우는 어떨까?

 

let res = {
  func : () => { // do something }
}

위 경우 res가 undefined인 상태에서 res.func()를 실행하려고 한다면 에러가 발생한다.

 

이런 타입과 관련한 에러를 직접, 실행하던 도중에 발견한다면 찾는데 시간이 오래 걸린다.

 

자바스크립트 타입에 관련한 에러를 컴파일시 발견할 수 있게 만든것이 타입스크립트다.

 

타입스크립트

 

https://www.typescriptlang.org/

 

TypeScript - JavaScript that scales.

State of the art JavaScript TypeScript offers support for the latest and evolving JavaScript features, including those from ECMAScript 2015 and future proposals, like async functions and decorators, to help build robust components. These features are avail

www.typescriptlang.org

 

node를 사용하고 있다면 다음 명령을 통해 설치할 수 있다.

 

npm install -g typescript

 

타입스크립트와 자바스크립트는 다음과 같은 차이가 존재한다.

 

var a = 1; // number
var b = '2'; // string
console.log(a+b) // "12"
var a:number = 1; 
var b:string = '2'; 
console.log(a+b)

첫 번째 코드는 javascript 코드이다. a와 b가 다른타입인데 + 연산을 수행하고, 이 연산이 문자열의 합을 출력한다.

이는 생각보다 자주 발생할 수 있는 문제인데, 특히 숫자의 경우 문자열로 처리한 뒤 저장할 수 있기 때문이다.

 

타입스크립트에서는 a와 b의 타입을 지정해 줄 수 있으므로 연산 전에 에러를 발생시킨다.

 


 

대부분의 초보자가 자바스크립트를 접할 때 가장 난해하게 여기는 것이 바로 타입이라고 생각한다.

특히 처음 배울 때 변수에 어떤 값이던 할당할 수 있다는 점은 복잡한 프로그램을 개발하기 어렵게 한다.

 

실제 로직을 구현했다 하더라고 타입때문에 에러가 발생하는 경우 이를 파악하기 힘들 수도 있다.

 

만약 자바스크립트에 한계를 느끼기 시작했다면, 타입스크립트로 옮겨갈 기회이다!

자바스크립트 언어는 현재 매우 많은곳에 쓰이고 있다.

 

웹 개발자로서 백엔드, 프론트엔트를 가리지 않고 자바스크립트 만으로 개발을 할 수 있을 정도다.

(예를 들면 node express server + react)

 

특히 브라우저에서 자체적으로 자바스크립트를 지원해주기도 하고,

react나 vuejs등을 사용하는 경우는 전부 자바스크립트이다.

 

그리고 자바스크립트에서 '타입'을 지정해주는 타입스크립트 언어까지 나온 상태이니

자바스크립트만 제대로 할 줄 알아도 큰 이점이 된다.

 

글을 작성하는 시점에서 (2020.02.17) 티오베(TIOBE)에서 자바스크립트 언어의 순위를 확인해보니 7위를 기록하고 있었다.

 

그러면 다른언어와 구별되는 자바스크립트의 특징과, 사용법을 알아보자.

 

강의 링크

 

[LECTURE] 1) 자바스크립트 변수-연산자-타입 : edwith

들어가기 전에 컴파일 단계가 없는 자바스크립트의 type(형)은 실행단계에서 타입이 결정됩니다. 변수선언은 어떻게 정의하고, 자바스크립트의 타입은 어떤 것들이 있는지 확인해봅니다.... - 부스트코스

www.edwith.org


hello world

console.log("hello world");	// 이것도 되고
console.log('hello world')	// 이것도 된다

자바스크립트를 처음 배울 때 특이했던 점 중 하나는 바로 ; (세미콜론) 이 필요가 없다는 것이다.

 

그리고 C언어처럼 변수의 형태를 지정해 줄 필요가 없다. (var, let, const 는 scope를 설정)

 

자바스크립트 언어를 직접 확인해보고 싶은가??

 

크롬을 사용한다면 F12 (개발자 도구)를 열고 console 탭으로 진입하자!

 

개발자 도구에서 자바스크립트를 사용해 볼 수 있다.

크롬이 아니더라도 파이어폭스, 인터넷 익스플로러, 엣지 브라우저 등등 대부분의 브라우저에서 자바스크립트를 이용해 볼 수 있다.

 

만약 브라우저가 아닌 터미널에서 코드를 실행시키고 싶다면??

 

Node.js를 설치하는 것을 추천한다!

 

https://nodejs.org/ko/

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

Node.js가 설치되었는지 확인하고 싶다면 터미널에서 다음을 실행해보자

node -v

제대로 설치되었다면 버전정보가 나타난다.

설치가 완료되었다면 실행하고 싶은 자바스크립트 코드를 작성한다.

파일명을 a.js라고 했을 때 다음과 같이 실행하자

 

// a.js
console.log("hello world");

a.js 파일이 존재하는 위치에서 node a.js를 실행하면 a.js가 실행횐다.

자바스크립트 문법

다음 코드를 살펴보자

var a = 2;
var a = "aaa";
var a = 'aaa';
var a = true;
var a = [];
var a = {};
var a = undefined;

a는 여러번 선언되었고, 각 경우마다 데이터 타입이 다르다.

그러나 이는 전혀 문제를 일으키지 않는다.

 

사실 자바스크립트를 이루고 있는 모든것이 객체이다.

 

일단 모든 것이 객체이기 때문에 형태가 달라질 수 있다고 생각하자.

 

다음 코드를 실행해보자

 

var a;
console.log(a);	// undefined

도데체 이 undefined는 무엇인가??

 

undefined는 값이 할당되지 않은 상태이다. 이는 null과 다르다

 

undefined === null	// false
undefined == null	// true

직접 테스트해보자

위 예제는 자바스크립트에서 == 연산대신 === 연산을 사용해야 하는 중요한 이유 중 하나이다.

 

== 는 두 객체의 '값'이 같은지 확인하는 연산이다.

=== 는 두 객체의 '값'과 '타입'이 같은지 확인하는 연산이다.

 

typeof null		// "object"
typeof undefined	//"undefined"

그러면 자바스크립트에는 어떤 타입들이 존재할까?

 

  • undefined
  • null
  • boolean
  • number
  • string
  • object
  • function
  • array
  • Date
  • RegExp

여기까지 '대략 이것이 자바스크립트' 이다라는 내용의 글이였다.

다음에는 자바스크립트 type들의 성질에 대하여 알아보자.

+ Recent posts