느슨한 타입(loosely typed)의 동적(dynamic) 언어
로 특정한 value type에 얽매이지 않고, 모든 변수*(variable)는 모든 value type으로 할당되거나 재할당될 수 있다.
↔ TypeError
발생 위험이 있으며, 오류 발견이 어려운 편
함수에 전달된 피연산자 또는 인수가 해당 연산자나 함수가 예상하는 타입과 호환되지 않거나,
변경할 수 없는 값을 수정하려고 하거나, 부적절한 방법으로 값을 사용하려고 할 때.
TypeScript의 정적 타입을 이용하면 코드의 가독성을 높이고 예측할 수 있게 하며 디버깅이 용이하다.
// ___loosely typed/dynamic 예시
let foo = 42; // foo is now a number
foo = 'bar'; // foo is now a string
foo = true; // foo is now a boolean
1. 원시 값(Primitive type) :
언어의 최고 로우레벨에서 직접 표현되는 불변 데이터
Boolean / Null / Undefined / Number / BigInt / String / Symbol
2. 객체(Objects) : 식별자로 참조할 수 있는 메모리 상의 값 {key:value}
Properties
(2-1.) 참조형(Reference Type) : 값이 저장된 주소 값을 할당
Array / Function / RegExp / Map ...
암시적변환(implicit coercion)과 명시적변환(explicit coercion)
이 있다. 암시적변환은 연산자 작용으로 인해 일어나는 형변환을 말하고, 코드에서 명시적으로 변환하는 것을 말한다. Boolean
, Number
, String
세 가지의 형변환이 있다.
변수 선언 시 선언→초기화를 거친다. var
, let
, const
이 있다.
- var
,let
은 객체 재할당이 가능하다.
- const
는 객체 재할당이 불가능하다.(객체 속성은 변경 가능)
- let
, const
는 변수 중복 선언이 불가능하다.
- 또는 객체를 동결하기 위한Object.freeze()
Method가 있다.
- let
은 일시적 사각지대(Temporal Dead Zone: TDZ) 구간에 존재
let a // 변수 선언(런타임 이전에 실행)
console.log(a) // output: undefined(자동으로 할당)
a = 123 // 값의 할당(런타임 중 실행)
let name = 'jisu' // 하나의 statement 로 압축
console.log(name) // output: jisu
name = 'Jisu Lee' // 값의 재할당
console.log(name) // output: Jisu Lee
console.log(age) // output: Uncaught ReferenceError: name is not defined
let name = '29' // 변수를 참조할 수 없음, 참조 에러
console.log(city) // output: Uncaught ReferenceError: Cannot access 'name' before initialization
const name = 'seoul'// 런타임 이전이므로 초기화되지 않음
자바스크립트 코드가 실행되는 환경
자바스크립트 엔진이 처음 코드를 실행할 때 Global Execution Context가 생성된다. 생성 과정에서 전역 객체인 Window Object (Node는 Global) 를 생성하고 this가 Window 객체를 가리키도록 한다.
자바스크립트 엔진은 함수가 호출 될 때마다 호출 된 함수를 위한 Execution Context를 생성한다. 모든 함수는 호출되는 시점에 자신만의 Execution Context를 가진다.
코드가 실행되면서 생성되는 Execution Context를 저장하는 자료구조
엔진이 처음 script를 실행할 때, Global Execution Context를 생성하고 이를 Call Stack에 push한다. 그 후 엔진이 함수를 호출할 때 마다 함수를 위한 Execution Context를 생성하고 이를 Call Stack에 push 한다. 자바스크립트 엔진은 Call Stack의 Top에 위치한 함수를 실행하며 함수가 종료되면 stack에서 제거(pop)하고 제어를 다음 Top에 위치한 함수로 이동한다.
모든 식별자는 호이스팅되는데, 호이스팅이란 런타임 전 먼저 실행되는 것을 말한다.
함수 코드 블록만을 지역 스코프로 인정하는 var 대신, 블록 레벨 스코프를 지원하는 const와 let을 사용하는 것을 권장한다.
스코프는 식별자*(Identifier)의 유효범위를 말하는데, var
는 함수 레벨 스코프를 제외하고 전역 스코프, let
, const
는 블록 레벨 스코프이다.
let v = "전역 변수";
function a() { //function a Execution Context(EC)
let v = "지역 변수";
function b() { //function b Execution Context
console.log(v); // expected output: "지역 변수"
}
b();
} //Global Execution Context
a();
자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프로 이동하면서 선언된 변수를 검색한다.
여러 스코프에서 동일한 식별자를 선언한 경우, 무조건 스코프 체인 상에서 가장 먼저 검색된 식별자에만 접근 가능하다. ⇒ 변수 은닉화(variable shadowing)
객체에서 속성을 직접 접근하지 못하게 숨기는 것. 내부 데이터, 내부 연산을 외부에서 접근하지 못하도록 은닉(hiding) 혹은 격리(isolation)시키는 것을 말한다. 변수에 접근지정자를 private 로 지정하고 setter, getter 를 사용해 변수의 접근, 제어한다
function a(){
let temp = 'a'
return temp;
}
console.log(temp) //expected output error: temp is not defined
const result = a()
console.log(result); //a
==
(Equal Operator)와 ===
(Strict Equal Operator)
===
는 type이 달라도 false다. (*=
은 할당연산자)
var a = 1; var b = "1";
console.log(a == b); // true
console.log(a === b); // false
console.log(true == 1); // true
console.log(true === 1); // false
console.log(0 == "0"); // true
console.log(0 === "0"); // false
console.log(0 == ""); // true
console.log(0 === ""); // false
var a = [1,2,3];
var b = [1,2,3];
console.log(a == b); // false
console.log(a === b); // false
//배열 또는 객체는 메모리 주소로 인해 === 에서 false
var x = {};
var y = {};
var z = y;
console.log(x == y) // false
console.log(x === y) // false
console.log(y === z) // true
console.log(y == z) // true
//z에 y를 할당하면서 같은 메모리 주소를 사용해서 true
// 함수 선언문
function sum(a,b) {
return a + b;
}
//함수 표현식
const sum = function(a,b) {
return a + b;
}
함수 선언문은 함수 전체를 호이스팅
한다. 정의된 범위의 맨 위로 호이스팅되서 함수 선언 전에 함수를 사용할 수 있다.
함수 표현식은 별도의 변수에 할당하게 되는데, 변수는 선언부와 할당부를 나누어 선언부만 호이스팅
한다. 중복적으로 동명의 함수를 쓰게 된다면 함수 표현식을 사용해 오류를 예방할 수 있다.
참조값의 복사는 메모리 주소로 인해 두 가지 복사 방법이 있다.
Object.assign()
, 전개연산자cloneDeep
사용, JSON.stringify()
와 JSON.parse()
undefined
: 변수에 값이 할당되지 않았거나, 함수가 값을 반환하지 않을 때
null
: 의도적으로 비어있음
typeof null // "object" (하위호환 유지를 위해 "null"이 아님)
typeof undefined // "undefined"
null === undefined // false
null == undefined // true
null === null // true
null == null // true
!null // true
isNaN(1 + null) // false
isNaN(1 + undefined) // true
let b = 1;
function hi () {
const a = 1;
let b = 100;
b++;
return a
return b
console.log(a,b); // expected output: 1, 101
}
console.log(a); // expected output: a is not defined
console.log(b); // expected output: 1 lien1
hi();
console.log(b); // expected output: 1 lien1
console.log(a);
에서a is not defined
에러가 나는 것을 볼 수 있다. 함수 코드 블록은 지역 스코프이므로 a의 변수 선언을 함수 밖에서 하면 에러를 해결할 수 있다.let b = 1; const a = 1; function hi () { let b = 100; b++; return a return b console.log(a,b); // expected output: 1, 101 } console.log(a); // expected output: 2 lien2 console.log(b); // expected output: 1 lien1 hi(); console.log(b); // expected output: 1 lien1