JS___2

HJ·2022년 5월 20일
0

Javascript__

목록 보기
2/2
post-thumbnail

5.20

Javascript

객체 기반스크립트 프로그래밍 언어
웹 브라우저 내에서 주로 사용하며, 다른 응용 프로그램의 내장 객체에도 접근할 수 있는 기능을 가지고 있다. 또한 Node.js와 같은 런타임 환경과 같이 서버 프로그래밍에도 사용되고 있다.
느슨한 타입(loosely typed)의 동적(dynamic) 언어입니다.
JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며,
모든 타입의 값으로 할당 (및 재할당) 가능합니다.

Javascript 자료형

숫자형 ( number )

정수 및 부동소수점 숫자(foationg point number)를 나타낸다.
숫자형엔 일반적인 숫자 외에
Infinity, -Infinity, NaN같은 '특수 숫자 값(special numeric value)'이 포함된다.
Nan : 계산 중 에러가 발생했다는 것을 나타내주는 값

ex :: 문자열 / 숫자

et s = "가";
et n = 123;
console.log(s/n) ---> NaN

BigInt

표준으로 채택된 지 얼마 안 된 자료형으로, 길이에 상관없이 정수를 나타낼 수 있다.
정수 리터럴 끝에 n을 붙이면 만들 수 있다.

const bigInt = 1234343143432353312545325345n;

문자형 ( string )

문자열을 따옴표로 묶는다.
큰따옴표: "Hello"
작은따옴표: 'Hello'
역 따옴표(백틱, backtick): hello
역 따옴표로 변수나 표현식을 감싼 후 ${…}안에 넣어주면, 아래와 같이 원하는 변수나 표현식을 문자열 중간에 쉽게 넣을 수 있습니다.

let name = "John";

// 변수를 문자열 중간에 삽입
alert( `Hello, ${name}!` ); // Hello, John!

// 표현식을 문자열 중간에 삽입
alert( `the result is ${1 + 2}` ); // the result is 3

불린형 ( boolean )

불린형(논리 타입)은 true와 false 두 가지 값밖에 없는 자료형입니다.
불린형은 긍정(yes)이나 부정(no)을 나타내는 값을 저장할 때 사용합니다.
true긍정, false부정을 의미합니다.

let isGreater = 4 > 1;

alert( isGreater ); // true (비교 결과: "yes")

null

null 값은 지금까지 소개한 자료형 중 어느 자료형에도 속하지 않는 값입니다.
null 값은 오로지 null 값만 포함하는 별도의 자료형을 만듭니다.

let age = null;

let age = null;나이(age)를 알 수 없거나 그 값이 비어있음을 보여줍니다.

undefined

undefined는 '값이 할당되지 않은 상태’를 나타낼 때 사용합니다.
undefined 값도 null 값처럼 자신만의 자료형을 형성합니다.
변수는 선언했지만, 값을 할당하지 않았다면 해당 변수에 undefined가 자동으로 할당됩니다.

let age;

alert(age); // 'undefined'가 출력됩니다.

개발자가 변수에 undefined를 명시적으로 할당하는 것도 가능하긴 합니다. ( 권장하지 않음 )

let age = 100;

// 값을 undefined로 바꿉니다.
age = undefined;

alert(age); // "undefined"

객체형 ( object )

객체(object)형은 특수한 자료형입니다.
객체형을 제외한 다른 자료형은 문자열이든 숫자든 한 가지만 표현할 수 있기 때문에
원시(primitive) 자료형
이라 부릅니다.

반면 객체는 데이터 컬렉션이나 복잡한 개체(entity)를 표현할 수 있습니다.

원시값 : 객체를 제외한 모든 타입은 불변 값(변경할 수 없는 값)을 정의합니다.
(C언어와는 달리) 문자열은 불변합니다. 이런 일련의 타입을 "원시값"이라고 합니다.

심볼형 ( symbol )

심볼(symbol)형은 객체의 고유한 식별자(unique identifier)를 만들 때 사용됩니다.


undefined , null

undefined -- 변수 선언 후, 값을 할당하지 않은 상태 ( 자료형이 없는 상태 )

  • 선언만 하고 초기화 되지 않은 변수의 타입이나 값
  • 객체에 정의 되지않은 속성의 타입이나 값

null -- 변수 선언 후, 빈 값을 할당한 상태 ( 빈 객체 )

  • 명시적으로 아무것도 없는 비어있는 상태를 나타낸다.
  • typeof = Object이며 값은 null 이다.

== , ===

== )) value와 value를 비교한다
=== )) value와 data type을 비교한다

let a = 5; 
a = 5 // true
a = "5" // true

a === 5 // true
a === "5" // false

++ typeof 연산자
typeof 연산자는 인수의 자료형을 반환합니다.
자료형에 따라 처리 방식을 다르게 하고 싶거나 변수의 자료형을 빠르게 알아내고자 할 때 유용합니다.
typeof 연산자는 두 가지 형태의 문법을 지원합니다.

연산자: typeof x
함수: typeof(x)

ypeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol"

typeof Math // "object"  (1)

typeof null // "object"  (2)

typeof alert // "function"  (3)
  • Math는 수학 연산을 제공하는 내장 객체이므로 "object"가 출력됩니다.

  • typeof null의 결과는 "object"입니다.
    null은 별도의 고유한 자료형을 가지는 특수 값으로 객체가 아니지만,
    하위 호환성을 유지하기 위해 이런 오류를 수정하지 않고 남겨둔 상황입니다.
    언어 자체의 오류이므로 null이 객체가 아님에 유의합니다.

  • typeof는 피연산자가 함수면 "function"을 반환합니다.
    그러므로 typeof alert는 "function"을 출력해줍니다.
    그런데 '함수’형은 따로 없습니다. 함수는 객체형에 속합니다.
    하위 호환성을 유지하기 위해 이런 오류를 수정하지 않고 남겨둔 상황입니다.


Javascript 문제점

  1. 브라우저에 종속적
    브라우저에서 돌아가는 Javascript는 브라우저에 종속적일 수 밖에 없다.
    내가 작성한 Javascript 코드가 어떤 브라우저에서 돌아가느냐에 따라
    개별적으로 신경써줘야할 부분이 많다는 것을 의미한다.
    문제가 없던 코드도 브라우저의 정책이나 지원에 따라 다르게 작동할 수 있다는 것이다.

  2. 불변성을 제공해주지 않는다는 것
    함수형 프로그래밍을 지원하는 것이 장점인 Javascript,
    함수형과 밀접한 관계인 불변성을 지원하지 않는다는 건 꽤 모순적이다.
    함수형이 대세로 떠오르는 요즘 같은 때에는 치명적인 단점이라고 볼 수 있다.

  3. 동적
    언제든 속성을 추가, 삭제, 수정할 수 있다.
    클래스 밖에서도 언제든 클래스의 속성을 바꿀 수 있다.
    함수형 프로그래밍에서 불변성은 아주 중요한 개념인데,
    Javascript는 너무 쉽게 객체를 변경시킬 수 있다.
    const라는 키워드만으로는 함수형 프로그래밍이 요구하는 수준의 불변성을 실현하기 어렵다.

    *const**로 객체 선언 후 객체의 주소값 자체를 변경시킬 수는 없지만,
    객체 내부의 속성이 변경되는 것 까지는 막지 못한다.

    객체의 속성값에 어떤 값이 추가되든 수정되든 기존 객체의 주소값은 동일한데,
    그것까지 const가 캐치할 수 없다.
    정확히 얘기하면 const는 할당된 값이 상수가 되는 것이 아니고, 바인딩 된 값이 상수가 되는 것


Javascript 객체, 불변성

Immutability(변경불가성)는 객체가 생성된 이후 그 상태를 변경할 수 없는 디자인 패턴을 의미한다. Immutability은 함수형 프로그래밍의 핵심 원리이다.

객체는 참조(reference) 형태로 전달하고 전달 받는다.
의도하지 않은 객체의 변경이 발생하는 원인의 대다수는 “레퍼런스를 참조한 다른 객체에서 객체를 변경”하기 때문이다.

var str = 'Hello';
str = 'world';
  • ‘Hello’를 수정하는 것이 아니라 새로운 문자열 ‘world’를 메모리에 생성하고
    식별자 str은 이것을 가리킨다.
    이때 문자열 ‘Hello’와 ‘world’는 모두 메모리에 존재하고 있다.
    변수 str은 문자열 ‘Hello’를 가리키고 있다가 문자열 ‘world’를 가리키도록 변경되었을 뿐이다.

데이터 타입 ( 기본형 , 참조형 )

기본(원시)형 : Number, String, Boolean, null, undefined, Symbol
기본형 데이터들은 그 자체로 비교가 가능하다.

참조형 : 대표적으로 객체(Object)
그 하위에 배열(Array), 함수(Function), 정규표현식(RegExp), Map, Set, WeakMap, WeakSet
참조형 데이터들은 프로퍼티(property)와 데이터(data), 즉 key = value로 묶인 쌍들로
이루어져 있습니다. 프로퍼티명은 변수와 비슷한 성질을 지니고 있고 변수명과 실제 데이터는
주소값을 통하여 연결되어 있는데 프로퍼티와 데이터 사이에서도 같은 동작을 합니다.

두 타입의 가장 대표적인 차이

  • 기본형에는 바로 값을 그대로 할당한다는 것
  • 참조형에는 값이 저장된 주소값을 할당(참조) 한다는 것

Javascript 형변환 ( 원시형의 형변환 )

함수와 연산자에 전달되는 값은 대부분 적절한 자료형으로 자동 변환 된다.
이런 과정을 형 변환이라고 한다.
ex :: aleat가 전달받은 값의 자료형과 관계없이
이를 문자열로 자동 변환하여 보여주는 것
ex :: 산술 연산을 위해 전달받은 값을 숫자로 변환하는 경우


문자형 변환

String(value) 함수를 호출해 전달받은 값을 문자열로 변환 할 수도 있습니다.

let value = true;
alert(typeof value); // boolean

value = String(value); // 변수 value엔 문자열 "true"가 저장됩니다.
alert(typeof value); // string

숫자형 변환

Number(value) 함수를 사용하면 주어진 값(value)을 숫자형으로 명시해서 변환할 수 있습니다.

let str = "123";
alert(typeof str); // string

let num = Number(str); // 문자열 "123"이 숫자 123으로 변환됩니다.

alert(typeof num); // number
  • 숫자형 값를 사용해 무언가를 하려고 하는데 그 값을 문자 기반 폼(form)을 통해 입력받는 경우엔, 이런 명시적 형 변환이 필수입니다.
  • null과 undefined은 숫자형으로 변환 시 결과가 다르다는 점에 유의하시기 바랍니다.
    null은 0이 되고 undefined는 NaN이 됩니다.

불린형 변환

이 형 변환은 논리 연산을 수행할 때 발생합니다
숫자 0, 빈 문자열, null, undefined, NaN과 같이 직관적으로도
“비어있다고” 느껴지는 값들은 false가 됩니다.
그 외의 값은 true로 변환됩니다.

alert( Boolean(1) ); // 숫자 1(true)
alert( Boolean(0) ); // 숫자 0(false)

alert( Boolean("hello") ); // 문자열(true)
alert( Boolean("") ); // 빈 문자열(false)

불변 객체를 만드는 방법

어떤 객체 내부의 프로퍼티들을 변경할 수 없도록 되어있는 객체

Object.freeze()

Javascript에서 기본적으로 제공하는 메소드인 Object.freeze() 메소드
공식 문서에서는 "객체를 동결하기 위한 메소드"라고 적혀있다.

let test = {
    name : 'kim'
}
Object.freeze(test);

test변수key value를 가진 객체를 바인딩 후 Object.freeze(test)를 사용해
바인딩 된 변수를 동결 객체로 만들었다. 때문에 test 객체는 객체의 속성을 변경하는 시도가 불가능하다.

test.name = 'Jung';
console.log(test) // {name: 'kim'}

▲▲▲위와 같은 속성을 변경하는 시도는 무시된다.

하지만... 객체의 재할당이 가능하다.

test = {
    age : 15
};
console.log(test); 
  • 때문에 Object.freeze()도 불변 객체라고 할 수는 없다..

const와 Object.freeze()를 조합한다면...?

const(재할당 불가) + Object.freeze() (개체속성 변경불가)

▼▼▼ 이렇게 사용 가능하다.

const test = {
    'name' : 'jung'
};

Object.freeze(test);

객체의 재할당, 객체의 속성 변경을 금지하는 불변 객체가 된다.


얕은 복사, 깊은 복사

얕은 복사
객체를 복사할 때 기존 값과 복사된 값이 같은 참조를 가리키고 있는 것을 말한다.
객체 안에 객체가 있는 경우 한 개의 객체라도 기존 변수의 객체를 참조하고 있다.

const a = 'a';
let b = 'b';
b = 'c';
console.log(a); // 'a';
console.log(b); // 'c';
  • 기존 값에 영향을 끼치지 않는다.

깊은 복사
객체의 실제 값을 복사
깊은 복사된 객체는 객체 안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체이다.

const object = {
a: "a",
number: {
one: 1,
two: 2,
},
arr: [1, 2, [3, 4]],
};
const copy = JSON.parse(JSON.stringify(object));
copy.number.one = 3;
copy.arr[2].push(5);
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // false
console.log(object.arr === copy.arr); // false
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ] }

출처: https://bbangson.tistory.com/78 [뺑슨 개발 블로그]

호이스팅, TDZ

호이스팅이란?
인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것

  • var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화한다.

  • let, const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않는다.

다만, 선언과 초기화를 함께 수행하는 경우
선언 코드까지 실행해야 변수가 초기화된 상태가 됨을 주의해야 한다.

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

catName("호랑이");

/*
결과: "제 고양이의 이름은 호랑이입니다"
*/

↑ 결과는 같다 ↓

catName("클로이");

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

/*
결과: "제 고양이의 이름은 클로이입니다"
*/

선언만 호이스팅 대상

JavaScript는 초기화를 제외한 선언만 호이스팅합니다.
변수를 먼저 사용하고 그 후에 선언 및 초기화가 나타나면, 사용하는 시점의 변수는
기본 초기화 상태(var 선언 시 undefined, 그 외에는 초기화하지 않음)입니다.

console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화

console.log(num); // ReferenceError
num = 6; // 초기화
  • 선언 없이 초기화만 존재하기 때문에 호이스팅이 없고,
    변수를 읽으려는 시도에서
    ReferenceError 예외가 발생

TDZ

스코프의 시작 지점부터 초기화 시작 지점까지의 구간 ( Temporal Dead Zone )

변수 선언 3단계
선언 단계(Declaration phase)
공간을 확보하고 변수명과 주소를 매칭시키는 과정
변수를 실행 컨텍스트의 변수 객체에 등록하는 단계를 의미합니다.
이 변수 객체는 스코프가 참조하는 대상이 됩니다.

초기화 단계(Initialization phase)
실행 컨텍스트에 존재 하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계 입니다.
이 단계에서 할당된 메모리에는 undefined로 초기화 됩니다.

할당 단계(Assignment phase)
해당 변수가 가리키는 주소의 공간에 데이터를 저장하는 과정
사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계 입니다.


함수 선언식, 함수 표현식

함수 선언식
함수명이 정의되어 있고, 별도의 할당 명령이 없는 것

함수 표현식
정의한 function을 별도의 변수에 할당하는 것

함수 선언식과 함수 표현식의 차이 (호이스팅)

함수 선언식함수 전체를 호이스팅 합니다.
정의된 범위의 맨 위로 호이스팅 돼서 함수 선언 전에 함수를 사용할 수 있다는 것

함수 표현식별도의 변수에 할당하게 됩니다.
변수는 선언부나 할당부를 나누어 호이스팅 하게 됩니다.

:: ex

sum(50, 50); // 100
minus(100, 50) // Uncaught TypeError: minus is not a function

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

var minus = function (a,b) { // 함수 표현식
  return a - b;
}

var minus = function (a,b) { // 함수 표현식
  return a - b;
}

sum(50, 50); // 100
minus(100, 50) // 50

function sum(a, b) { // 함수 선언식
  return a + b;
};
  • 함수 선언식으로 작성한 함수는, 함수 전체가 호이스팅 된다고 하였는데,
    전역적으로 선언하게 되면, 중복적으로 동명의 함수를 쓰게 될 수 있다.
    이를 방지하려면 함수 표현식으로 작성하면 된다.

var 변수 라이프사이클 ▼▼▼

var 키워드 변수는 변수를 선언하기 전에 선언 단계와 초기화 단계를 동시에 진행한다.

그래서 Javascript는 실행 컨텍스트 변수 객체의 변수를 등록하고 메모리를
undefined로 만들어 버린다.

그렇기 때문에 변수를 선언하기 전에 호출을 해도 undefined로 호출이 되는
호이스팅이 발생한다.


let 변수 라이프사이클 ▼▼▼

let으로 선언된 변수는 var 키워드와는 다르게,
선언 단계와 초기화 단계가 분리되어서 진행된다.

그렇게 때문에 실행 컨텍스트에 변수를 등록했지만,
메모리가 할당 되지 않아 접근할 수 없어 참조 에러(ReferenceError)가 발생한다.
이것을 보고 우리는 호이스팅이 되지 않는다고 오해할 수 있었다.

let 또한 선언 전, 실행 컨텍스트 변수 객체에 등록이 되어 호이스팅이 되지만,
TDZ 구간에 의해 메모리가 할당되지 않아서 참조 에러(ReferenceError)가 발생하는 것이다.

실행 컨텍스트 & 콜 스택

실행할 코드에 제공할 환경 정보들을 모아놓은 객체
Javascript의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이다.

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

  • 호이스팅 발생 ( 선언된 변수를 위로 끌어올린다 )
  • 외부 환경 정보를 구성
  • this 값을 설정

이로 인해 다른 언어에서 발견할 수 없는 특이한 현상들이 발생한다.

실행 컨텍스트 구성

  • 전역공간은 자동으로 컨텍스트로 구성
  • 함수를 실행
  • eval() 함수를 실행
  • block을 생성
    ▲▲▲▲▲ 위의 것을 이용하면 call stack에 쌓이게 된다.
var a = 1; // 전역 컨텍스트
function outer () { // outer 컨텍스트
  function inner () { // inner 컨텍스트
    console.log(a); // undefined
    var a = 3;
    console.log(a); // 3
  }
  inner();
  console.log(a); // 1
}
outer();
console.log(a); // 1
profile
Development log

0개의 댓글