JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당) 이 가능하다!
동적 타입 언어
자바스크립트, 파이썬, 루비
정적 타입 언어
러스트, C++, 고, 자바
동적 타입 언어 : 변수에 값을 할당할때 타입이 바뀌는 것을 허용함
정적 타입 언어 : 허용하지 않음
Number("273")
//273
Number("$273")
//NaN
숫자 연산자(-, *, /) 를 사용하면 문자형이 숫자형으로 변환됨
더하기는 안됨! (불은 됨)
"52" - 0
// 52
"52" + 5
// 525
true - 0
// 1
String(52)
// "52"
String(true)
// "true"
더하기(+) 연산자를 사용하면 숫자가 문자열로 변환됨
빈 문자열을 더해 문자형으로 변환할 수 있음
273 + ""
// "273"
true + ""
//"true"
앞에 + 를 붙히면 숫자형이 됨
false로 변환되는 경우
0, "", null, undefined, NaN
나머지는 다 true로 변환됨!
Boolean(0)
// false
Boolean("hi")
// true
! 은 부정의 의미로 불의 값을 역전시킴 (true 면 false로, false면 true로 반환)
논리 부정 연산자를 두번 사용하면 (원래의)불 자료형으로 변환됨
!!273
// true
!!0
//false
'==' 연산자를 이용하여 서로 다른 유형의 두 변수의 [값] 비교
✌ '==='는 엄격한 비교를 하는 것으로 알려져 있다 ([값 & 자료형] -> true)
'10' == 10 true로 표시됨
null == undefined
“0” == 0
0 == false
“0” == false
위의 결과값은 모두 true 임.
== 이걸로 쓰면 데이터타입을 변환하기 때문!
데이터타입을 변환하지 않는 === 으로 써야한다!!
'10' === 10
// Print: false
'10' == 10
// Print: true
'10' !== 10
// Print: true
'10' != 10
// Print: false
런타임까지 타입에 대한 결정을 끌고 갈 수 있기 때문에 유연성이 높음
컴파일시 타입을 명시해주지 않아도 되기 때문에 빠르게 코드를 작성할 수 있음
실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있음.
동적타입 언어는 런타임 시 확인할 수 밖에 없기 때문에, 코드가 길고 복잡해질 경우 타입 에러를 찾기가 어려워짐.
이러한 불편함을 해소하기 위해 TypeScipt나 Flow 등을 사용할 수 있음.
원시 자료형, 값을 할당하지 않은 변수
원시 자료형, 어떤 값이 비어있음을 의도적으로 표현
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 //숫자가 아니다
매개변수가 숫자가 아닌지 확인하는 함수(NaN은 Not a Number입니다.)
매개변수가 숫자가 아니면 true, 숫자이면 false를 반환합니다.
let c = 1 + null
console.log(c) // 1
let d = 1 + undefined
console.log(d) // NaN
undefined 넘버로 형변환하면 NaN
null 넘버로 형변환 0
기본형 : 숫자 문자 불 눌 언디파인드 심볼
참조형 : 객체 (배열 함수 레그익셉 셋 맵)
컴퓨터는 a에 값을 할당하면 다른 공간에 abc를 저장하고 값에는 주소를 저장함
a가 값이 바뀌면?
5004에 새롭게 값을 할당하는게 아니라 5005(새로운 주소)에 데이터를 저장하고 값을 새로운 주소로 바꿔줌
a키의 값이 변경되면?
1. 5005라는 공간에 2를 저장
2. 저장된 주소에 감 > 주소에서 a가 저장된 곳을 감
3. a가 저장된 곳의 값을 5005로 변경
기본형에서는 obj의 값이 바뀌었는데, 참조형에서는 a가 변경되었음에도 obj의 값이 바뀌지 않았음!
만약 값이 변경되면?
참조된 데이터가 없는 경우를 참조카운팅이 0 이라고 표현하는데
참조카운팅이 0이된 대상은 가비지컬렉팅?이 되어 언젠가는 사라진다.
비교에 비용이 들지 않음 > 같은 값에는 오직 하나만 존재한다는 의미!!
-> 불변성
위에서 얘기해서 넘김
객체를 얼려서 누구도 그 객체를 수정하지 못하게 하는 것
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
객체를 정확하게 적어주면 객체도 불변해짐
얕은 복사는 객체의 참조값(주소 값)을 복사하고,
깊은 복사는 객체의 실제 값을 복사한다.
블로그에 둘다 정리함
[용어정리] 스코프(Scope)
[용어정리] 변수, 호이스팅, TDZ(Temporal Dead Zone)
실행 컨텍스트 : 우리가 작성한 코드가 실행되는 환경
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();
위 예제 코드는 다음과 같이 실행 될 것입니다.
이처럼 자바스크립트는 한 순간 하나의 작업만을 처리하며 동작하게 됩니다.
만약, 어떠한 함수의 실행이 오래걸린다면 어떨까요?
실행이 되는동안 브라우저가 멈춘 상태로 있을겁니다. 멈춘동안 사용자가 이것 저것 트리거를 발생시킨다면,
오래 걸리던 함수가 종료되는 순간 콜 스택에 주르륵 쌓이고 처리하게 될 것입니다.
혹은 응답 없는 페이지 창이 뜰지도 모릅니다
즉, 좋은 사용성은 아니란 것입니다.
스코프 체인 : 자기 자신의 스코프(scope)를 제외한 자신과 가장 가까운 변수 객체의 모든 스코프
각 스코프가 어떻게 연결되는지 보여주는 것을 뜻함
직접적으로 변경되면 안 되는 변수에 대한 접근을 막는 것
(function () {
var a = 'a';
})();
console.log(a); // a is not defined
함수 외부에서 a를 출력해보면, 아직 정의되지 않았다(a is not defined)는 에러메세지를 확인할 수 있습니다. 이러한 방식과 같이 직접적으로 변경되면 안 되는 변수에 대한 접근을 막는 것을 은닉화라고 합니다.
[항해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은 true임
"1"도 true임
결과는 true
===은 타입까지 맞아야 true로 표현됨
1은 숫자형, "1"은 문자형이므로
결과는 false
JavaScript의 자료형과 JavaScript만의 특성
JavaScript immutability - 6. Object freeze로 객체를 불변하게 만들기