프로그래밍 기초 - JavaScript

lezsuuu·2022년 7월 20일
0

JavaScript

목록 보기
3/6
post-thumbnail

JavaScript 살펴보기

느슨한 타입(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

JS types

1. 원시 값(Primitive type) :
언어의 최고 로우레벨에서 직접 표현되는 불변 데이터
Boolean / Null / Undefined / Number / BigInt / String / Symbol
2. 객체(Objects) : 식별자로 참조할 수 있는 메모리 상의 값 {key:value}
Properties
(2-1.) 참조형(Reference Type) : 값이 저장된 주소 값을 할당
Array / Function / RegExp / Map ...
기본형 데이터와 참조형 데이터

JS 형변환(coercion)

암시적변환(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'// 런타임 이전이므로 초기화되지 않음

실행 컨텍스트(Execution context)와 콜 스택(call stack)

Execution context

자바스크립트 코드가 실행되는 환경

1. Global Execution context

자바스크립트 엔진이 처음 코드를 실행할 때 Global Execution Context가 생성된다. 생성 과정에서 전역 객체인 Window Object (Node는 Global) 를 생성하고 this가 Window 객체를 가리키도록 한다.

2. Function Execution context

자바스크립트 엔진은 함수가 호출 될 때마다 호출 된 함수를 위한 Execution Context를 생성한다. 모든 함수는 호출되는 시점에 자신만의 Execution Context를 가진다.

자바스크립트는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생한다.

  • 호이스팅이 발생한다.
  • 외부 환경 정보를 구성한다.
  • this 값을 설정한다.

call stack

코드가 실행되면서 생성되는 Execution Context를 저장하는 자료구조

엔진이 처음 script를 실행할 때, Global Execution Context를 생성하고 이를 Call Stack에 push한다. 그 후 엔진이 함수를 호출할 때 마다 함수를 위한 Execution Context를 생성하고 이를 Call Stack에 push 한다. 자바스크립트 엔진은 Call Stack의 Top에 위치한 함수를 실행하며 함수가 종료되면 stack에서 제거(pop)하고 제어를 다음 Top에 위치한 함수로 이동한다.

호이스팅(hoisting)

모든 식별자는 호이스팅되는데, 호이스팅이란 런타임 전 먼저 실행되는 것을 말한다.

함수 코드 블록만을 지역 스코프로 인정하는 var 대신, 블록 레벨 스코프를 지원하는 const와 let을 사용하는 것을 권장한다.

스코프(scope)

스코프는 식별자*(Identifier)의 유효범위를 말하는데, var는 함수 레벨 스코프를 제외하고 전역 스코프, let, const는 블록 레벨 스코프이다.

스코프 체인(Scope Chain)

실행 컨텍스트의 렉시컬 환경을 '단방향'으로 연결한 링크드 리스트

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)

변수 은닉화(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

==(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 declartion)과 함수 표현식(function Expression)

// 함수 선언문
function sum(a,b) {
    return a + b;
}

//함수 표현식 
const sum = function(a,b) {
    return a + b;
}
  • 함수 선언문은 함수 전체를 호이스팅한다. 정의된 범위의 맨 위로 호이스팅되서 함수 선언 전에 함수를 사용할 수 있다.

  • 함수 표현식은 별도의 변수에 할당하게 되는데, 변수는 선언부와 할당부를 나누어 선언부만 호이스팅한다. 중복적으로 동명의 함수를 쓰게 된다면 함수 표현식을 사용해 오류를 예방할 수 있다.

얕은 복사(Shllow Copy)와 깊은 복사(Deep Copy)

참조값의 복사는 메모리 주소로 인해 두 가지 복사 방법이 있다.

  • 얕은 복사: 원래 값과 복사된 값이 같은 참조를 가리키고있는 것
    Object.assign(), 전개연산자
  • 깊은 복사: 원본과의 참조가 완전히 끊어진 객체를 생성
    → 재귀함수를 이용한 복사, lodash라이브러리 cloneDeep 사용, JSON.stringify()JSON.parse()

undefined와 null

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

실습과제

콘솔에 찍힐 b 값을 예상해보고, 어디에서 선언된 “b”가 몇번째 라인에서 호출한 console.log에 찍혔는지, 왜 그런지 설명해보세요. 주석을 풀어보고 오류가 난다면 왜 오류가 나는 지 설명하고 오류를 수정해보세요.
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

[기타정리]
- 할당(assignment): 변수에 값을 저장
- 선언(declaration): 변수명을 자바스크립트 엔진에 알리는 것
- 참조(reference): 변수에 저장된 값을 읽어 들이는 것
- variable ↔ constant
- 매개변수(parameter)
- 식별자(Identifier): 변수명, 함수명, 클래스명 등
- JavaScript는 managed language로 개발자가 메모리를 직접 제어할 수 없어 메모리에 붙인 이름을 붙인다.
- 선언 단계: 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알린다.
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당한다.
- 전역 스코프: 어디에서든지 참조가 가능한 값
- 지역 변수: 자신과 하위 지역 스코프에서만 유효
- 블록 레벨 스코프: if, for, while, try/catch 등 → 지역 스코프 생성
- TDZ: 선언 단계와 초기화 단계가 분리되어 진행되므로 발생
[참고자료]
https://developer.mozilla.org/ko/docs/Web/JavaScript/ 개괄
https://www.secmem.org/blog/2020/03/19/javascript-type-coercion/ JavaScript의 형변환
https://dorey.github.io/JavaScript-Equality-Table/ ==, === 테이블
https://steemit.com/kr-dev/@cheonmr/js-operator/ Equal Operator 예문
https://www.howdy-mj.me/javascript/var-let-const/ var, let, const의 차이 - 변수 선언 및 할당, 호이스팅, 스코프
profile
돌고 돌아 벨로그

0개의 댓글