[항해99] Javascript 과제

posinity·2022년 11월 18일
0

JavaScript

목록 보기
6/31

1. 🐤 JavaScript의 자료형과 JavaScript만의 특성은 무엇일까 ?

(1) 느슨한 타입(loosely typed)의 동적(dynamic) 언어

JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당) 이 가능하다!

동적 타입 언어
자바스크립트, 파이썬, 루비
정적 타입 언어
러스트, C++, 고, 자바

동적 타입 언어 : 변수에 값을 할당할때 타입이 바뀌는 것을 허용
정적 타입 언어 : 허용하지 않음

(2)JavaScript 형변환

숫자 자료형으로 변환하기

1. Number() 함수 사용

Number("273")
//273

숫자로 변환할 수 없을 때

Number("$273")
//NaN

자바스크립트의 자동 형변환 이용하기

숫자 연산자(-, *, /) 를 사용하면 문자형이 숫자형으로 변환됨
더하기는 안됨! (불은 됨)

"52" - 0 
// 52

"52" + 5
// 525

true - 0 
// 1

문자 자료형으로 변환하기

1. String() 함수 사용

String(52)
// "52"

String(true)
// "true"

2. 자바스크립트의 자동 형변환 이용하기

더하기(+) 연산자를 사용하면 숫자가 문자열로 변환됨

빈 문자열을 더해 문자형으로 변환할 수 있음

273 + ""
// "273"

true + ""
//"true"

앞에 + 를 붙히면 숫자형이 됨

불 자료형으로 변환하기

1. Boolean() 함수 사용하기

false로 변환되는 경우
0, "", null, undefined, NaN

나머지는 다 true로 변환됨!

Boolean(0)
// false

Boolean("hi")
// true

2. 논리 부정 연산자(!) 사용하기

! 은 부정의 의미로 불의 값을 역전시킴 (true 면 false로, false면 true로 반환)
논리 부정 연산자를 두번 사용하면 (원래의)불 자료형으로 변환됨

!!273
// true

!!0
//false

(3) ==, ===

'==' 연산자를 이용하여 서로 다른 유형의 두 변수의 [값] 비교
✌ '==='는 엄격한 비교를 하는 것으로 알려져 있다 ([값 & 자료형] -> true)

자바스크립트의 자동 형변환 기능

'10' == 10 true로 표시됨

null == undefined0== 0
0 == false0== false

위의 결과값은 모두 true 임.
== 이걸로 쓰면 데이터타입을 변환하기 때문!
데이터타입을 변환하지 않는 === 으로 써야한다!!

'10' === 10
// Print: false

'10' == 10
// Print: true

'10' !== 10
// Print: true

'10' != 10
// Print: false

(4) 느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점은 무엇이고 보완할 수 있는 방법에는 무엇이 있을지 생각해보세요.

  • 장점 :

런타임까지 타입에 대한 결정을 끌고 갈 수 있기 때문에 유연성이 높음
컴파일시 타입을 명시해주지 않아도 되기 때문에 빠르게 코드를 작성할 수 있음

  • 단점 :

실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있음.
동적타입 언어는 런타임 시 확인할 수 밖에 없기 때문에, 코드가 길고 복잡해질 경우 타입 에러를 찾기가 어려워짐.
이러한 불편함을 해소하기 위해 TypeScipt나 Flow 등을 사용할 수 있음.

(5)undefined와 null의 미세한 차이들을 비교해보세요.

undefined

원시 자료형, 값을 할당하지 않은 변수

null

원시 자료형, 어떤 값이 비어있음을 의도적으로 표현

undefined은 변수를 선언하고 값을 할당하지 않은 상태, null은 변수를 선언하고 빈 값을 할당한 상태(빈 객체)이다. 즉, undefined는 자료형이 없는 상태이다.
따라서 typeof를 통해 자료형을 확인해보면 null은 object로, undefined는 undefined가 출력되는 것을 확인할 수 있다.

typeof null // 'object' //빈 객체니까.
typeof undefined // 'undefined'
null === undefined // false //형이 다름
null == undefined // true //값이 같음. 둘다 비었음
null === null // true
null == null // true
!null // true
isNaN(1 + null) // false //숫자다 null이 0이 되므로 숫자
isNaN(1 + undefined) // true //숫자가 아니다 

isNaN()

매개변수가 숫자가 아닌지 확인하는 함수(NaN은 Not a Number입니다.)
매개변수가 숫자가 아니면 true, 숫자이면 false를 반환합니다.

let c = 1 + null
console.log(c) // 1

let d = 1 + undefined
console.log(d) // NaN

undefined와 null의 형변환

undefined 넘버로 형변환하면 NaN
null 넘버로 형변환 0

자료형 변환 표 참고

2. JavaScript 객체와 불변성이란 ?

(1) 기본형 데이터와 참조형 데이터


기본형 : 숫자 문자 불 눌 언디파인드 심볼
참조형 : 객체 (배열 함수 레그익셉 셋 맵)

기본형 데이터의 데이터 저장방법



컴퓨터는 a에 값을 할당하면 다른 공간에 abc를 저장하고 값에는 주소를 저장함
a가 값이 바뀌면?

5004에 새롭게 값을 할당하는게 아니라 5005(새로운 주소)에 데이터를 저장하고 값을 새로운 주소로 바꿔줌

참조형 데이터의 데이터 저장방법

  1. 참조형 데이터를 할당함
  2. 데이터가 여러개이기 때문에 한곳에 저장할 수 없음
  3. 주소 a부터 ~까지 데이터를 저장하겠다 하고 주소를 저장함
  4. 저장된 주소에 하나씩 데이터를 넣어줌 (기본형처럼)
  5. 이름에는 주소가 저장된 값을 넣어줌

a키의 값이 변경되면?

1. 5005라는 공간에 2를 저장
2. 저장된 주소에 감 > 주소에서 a가 저장된 곳을 감
3. a가 저장된 곳의 값을 5005로 변경

기본형에서는 obj의 값이 바뀌었는데, 참조형에서는 a가 변경되었음에도 obj의 값이 바뀌지 않았음!


만약 값이 변경되면?

참조된 데이터가 없는 경우를 참조카운팅이 0 이라고 표현하는데
참조카운팅이 0이된 대상은 가비지컬렉팅?이 되어 언젠가는 사라진다.

비교에 비용이 들지 않음 > 같은 값에는 오직 하나만 존재한다는 의미!!
-> 불변성

(2) JavaScript 형변환

위에서 얘기해서 넘김

(3) 불변 객체를 만드는 방법

Object.freeze

객체를 얼려서 누구도 그 객체를 수정하지 못하게 하는 것

let obj = {
  name : 'posi',
  score : [1,2]
}

obj.name = 'kim'

console.log(obj.name) // kim

freeze 함수를 사용하면?

let obj = {
  name : 'posi',
  score : [1,2]
}
Object.freeze(obj)

obj.name = 'kim'

console.log(obj.name) // 'posi' //이름을 바꿔도 원래의 값을 사용한다

한번 얼려진 값은 해동이 불가능함.
바꾸려면 복제해서 써야함.
추가도 못함!

let obj = {
  name : 'posi',
  score : [1,2]
}
Object.freeze(obj)

obj.city = 'jeju'
console.log(obj)
//{
  name: "posi",
  score: [1, 2]
}

하지만 객체의 값을 수정하면?

let obj = {
  name : 'posi',
  score : [1,2]
}
Object.freeze(obj)

obj.score.push(3)

console.log(obj)
//{
  name: "posi",
  score: [1, 2, 3]
}

데이터는 다른 곳에 저장되어있고 프로퍼티에는 그 래퍼런스만 저장되어있기 때문에 객체는 바뀜

객체는 어떻게 불변하게 만들까?

let obj = {
  name : 'posi',
  score : [1,2]
}
Object.freeze(obj.score)

obj.score.push(3)

console.log(obj) //"TypeError: Cannot add property 2, object is not extensible

객체를 정확하게 적어주면 객체도 불변해짐

(4) 얕은 복사와 깊은 복사

얕은 복사는 객체의 참조값(주소 값)을 복사하고,
깊은 복사는 객체의 실제 값을 복사한다.

3. 호이스팅과 TDZ는 무엇일까 ?

(1) 스코프, 호이스팅, TDZ

함수 선언문과 함수 표현식에서 호이스팅 방식의 차이

블로그에 둘다 정리함
[용어정리] 스코프(Scope)
[용어정리] 변수, 호이스팅, TDZ(Temporal Dead Zone)

(2) 실행 컨텍스트와 콜 스택

실행 컨텍스트 : 우리가 작성한 코드가 실행되는 환경


global execute context에서 실행되면
앞에 변수 아무것도 안붙히거나, var 쓰면 글로벌에 저장
let,const는 script에 저장

function execute context의 경우
앞에 아무것도 안붙힐때만 글로벌
나머지는 로컬에 저장된다
let,const는 블럭 안에서도 로컬로 들어간다.

콜 스택

자바스크립트 코드가 실행되며 생성되는 실행 컨텍스트를 저장하는 자료구조
1. 함수를 호출하면 실행 컨텍스트가 생성되고, 이를 콜 스택에 추가한 다음 함수를 수행하기 시작합니다.
2. 함수에 의해 호출되는 모든 함수(내부 함수들)는 콜 스택에 추가되고 해당 위치에서 실행합니다.
3. 함수의 실행이 종료되면 해당 실행 컨텍스트를 콜 스택에서 제거한 후 중단 된 시점부터 다시 시작합니다.
4. 만약 스택이 할당 된 공간보다 많은 공간을 차지하면 'stack overflow'에러가 발생합니다.

unction foo() {
  console.log("foo");
}

function bar() {
  console.log("bar");
}

function baz() {
  foo();
  console.log("baz");
  bar();
}

baz();

위 예제 코드는 다음과 같이 실행 될 것입니다.

  1. baz 함수를 호출할 때까지 모든 함수를 무시합니다.
  2. baz 함수를 호출합니다.
  3. baz 함수를 호출하여 생성 된 실행 컨텍스트를 콜 스택에 추가합니다.
  4. baz 함수 내의 모든 코드를 읽기 시작합니다.
  5. foo 함수를 호출합니다.
  6. foo 함수를 호출하여 생성 된 실행 컨텍스트를 콜 스택에 추가합니다.
  7. foo 함수 내의 모든 코드를 읽기 시작합니다.
  8. foo 함수 내의 모든 코드를 읽었다면 해당 실행 컨텍스트를 제거합니다.
  9. foo 함수가 호출 된 라인으로 돌아와 나머지를 계속 실행합니다.
  10. bar 함수도 5~9과 마찬가지로 실행됩니다.
  11. baz 함수 내의 모든 코드를 모두 읽었으므로 baz함수가 콜 스택에서 제거됩니다.
    결과는 foo, baz, bar 순서대로 출력 될 것입니다.

이처럼 자바스크립트는 한 순간 하나의 작업만을 처리하며 동작하게 됩니다.
만약, 어떠한 함수의 실행이 오래걸린다면 어떨까요?
실행이 되는동안 브라우저가 멈춘 상태로 있을겁니다. 멈춘동안 사용자가 이것 저것 트리거를 발생시킨다면,
오래 걸리던 함수가 종료되는 순간 콜 스택에 주르륵 쌓이고 처리하게 될 것입니다.
혹은 응답 없는 페이지 창이 뜰지도 모릅니다
즉, 좋은 사용성은 아니란 것입니다.

(3) 스코프 체인, 변수 은닉화

스코프 체인 : 자기 자신의 스코프(scope)를 제외한 자신과 가장 가까운 변수 객체의 모든 스코프
각 스코프가 어떻게 연결되는지 보여주는 것을 뜻함

은닉화

직접적으로 변경되면 안 되는 변수에 대한 접근을 막는 것

(function () {
  var a = 'a';
})();

console.log(a); // a is not defined

함수 외부에서 a를 출력해보면, 아직 정의되지 않았다(a is not defined)는 에러메세지를 확인할 수 있습니다. 이러한 방식과 같이 직접적으로 변경되면 안 되는 변수에 대한 접근을 막는 것을 은닉화라고 합니다.

4. 실습 과제

JavaScript 간단퀴즈

[항해99] Javascript 간단 퀴즈
길어져서 글 새로 팜!

콘솔 값 예상하기

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

let b = 1;

function hi () {

const a = 1;

let b = 100;

b++;

console.log(a,b);

}

//console.log(a);

console.log(b);

hi();

console.log(b);

// 1
1
101
1

나의 풀이

let b = 1;

function hi () {

const a = 1;

let b = 100;

b++; // b = 101

console.log(a,b); // a=1 , b = 101

}

//console.log(a); // 무시함

console.log(b); // 1 - 1번째 라인

hi(); // 1, 101

console.log(b); // 1 - 1번째 라인

두 값이 다른 이유를 설명해보세요.

1 == "1";
1 === "1";

1 == "1"

==이기 때문에 양쪽은 불 자료형으로 변환해야함
1은 true임
"1"도 true임

결과는 true

1 === "1"

===은 타입까지 맞아야 true로 표현됨
1은 숫자형, "1"은 문자형이므로

결과는 false

참고자료

동적 타입 언어와 정적 타입 언어는 뭐가 다른걸까요?

JavaScript의 타입과 자료구조

JavaScript의 자료형과 JavaScript만의 특성

정적타입 언어 vs. 동적타입 언어 특징 비교하기

undefined와 null의 차이점을 설명하세요

코어 자바스크립트 - 데이터타입 (기본형과 참조형)

JavaScript immutability - 6. Object freeze로 객체를 불변하게 만들기

JavaScript - Execute context

8. Javascript의 콜 스택과 이벤트 루프

profile
문제를 해결하고 가치를 제공합니다

0개의 댓글