🐤 JavaScript의 자료형과 JavaScript만의 특성은 무엇일까 ?참고 블로그 정말 감사합니다. 덕분에 공부가 잘 되었습니다.
느슨한 타입(loosely typed)의 동적(dynamic) 언어
-> JS의 변수는 어떤 특정 타입과 연결되지 않으며 모든 타입의 값으로 할당 / 재할당이 가능(뭐랄까.. TypeScript와 좀 다른 면이 있지 않을까 싶다.)
JavaScript 형변환
-> 암시적 변환 : JS엔진이 필요에 따라 자동으로 변환
-> 명시적 변환 : 개발자가 의도를 가지고 변환
==, === : 변수 유형 고려(===) / 고려치 않음(==)
===를 사용하는 것 권장하는게 좋을 듯, 엄격한 비교
느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점은 무엇이고 보완할 수 있는 방법에는 무엇이 있을지 생각해보세요.
-> 실행 도중 예상치 못한 타입에러가 발생할 가능성이 높다. 동적 타입 언어는 런타임 시 확인할 수밖에 없기 때문에 코드가 길고 복잡할수록 타입에러를 찾기 어려워진다.
그래서 나온게 TypeScript
undefined와 null의 미세한 차이들을 비교해보세요.
-> undefined은 변수를 선언하고 값을 할당하지 않은 상태, null은 변수를 선언하고 빈 값을 할당한 상태(빈 객체)이다. 즉, undefined는 자료형이 없는 상태
undifined는 프로젝트 하면서도 종종 나온 에러. 변수만 있고 값이 없을 경우 주로 많이 있었음.
기본형 데이터와 참조형 데이터
-> 기본형 : 논리형, 정수형, 실수형, 문자형
-> 참조형 : 배열, 클래스, 인터페이스
JavaScript 형변환
-> str to int : parseInt, parseFloat, Number
-> int to str : String, .toString, toFixed, 숫자+"문자열"
불변 객체를 만드는 방법
-> 변하지 않는 객체를 만드는 방법.
// Object freeze 객체를 불변하게 만들기
let test = {
name : 'kim'
}
Object.freeze(test);
test.name = 'Jung';
console.log(test)
(얕은 복사) -> 객체 복사 시 해당 객체만 복사하여 새 객체 생성 : 원본과 같은 메모리를 참조하기 때문에 복사 값이 변경되면 원본이 변경된다.
(깊은 복사) -> 객체 복사 시 인스턴스 변수까지 모두 복사하는 형태로 새 주소에 담겨 참조를 공유하지 않음. 즉 변경사항이 있어도 따로 따로..
가끔 보면 var로 변수를 정의했을 때 선언도 전에 변수가 나올 때가 있는데 이 때 호이스팅이 일어났다고 볼 수 있다.
(TDZ) -> 예시 코드
let age = 30;
function showAge() {
console.log(age) //여기서 위에 age에 잘 접근할수 있습니다.
}
showAge();
let age = 30;
function showAge() {
console.log(age) //2) TDZ 영역이 되어서 ReferenceError 에러를 볼수 있습니다.
let age = 20; //1) 이것을 추가하면
}
showAge();
TDZ 시맨틱은 선언 전에 변수에 접근하는 것을 금지한다. TDZ는 징계를 내린다: 변수 선언 전에 어떤 것도 사용하지 않는다. 이러한 이유로 var는 사용 피하는 것이...
let, const, class는 TDZ에 걸린다. 그 외에도 많은 부분들이 걸린다.(위에 3번 참고 블로그 참고....
function sum(a,b) {
return a + b;
}
(함수 표현식) -> 별도의 변수에 할당되는 것. 변수는 선언부와 할당부로 나누어 호이스팅
const sum = function(a,b) {
return a + b;
}
선언식으로 작성한 함수는 전체가 호이스팅, 전역적으로 선언하게 되면 중복적으로 동명의 함수를 쓰게 되었을 때 원치 않은 결과 초래. 이를 방지하고자 함수 표현식으로 작성
-> 1~3 : 값 변경 기능 유무, 스코프 범위, 호이스팅 기능 유무차이가 있다.(e.g. const는 값 변경이 안 된다. var는 함수 스코프고 나머진 블록 스코프다. var는 호이스팅이 된다...)
-> 4 : 함수 실행 위해서는 이름(식별자)가 필요. 이는 스코프에서 값을 참조하기 위해서이다.
(e.g) 엔진이 함수 선언문을 만나면 식별자를 관리하는 특별한 집합(EnviromentRecord)에 함수의 이름을 식별자로 넣고 함수 객체를 생성하여 참조합니다. 그리고 함수 실행 구문 중 foo를 만나면 값을 스코프를 통해 가져옵니다. 그 다음 구문이 () 이므로 실행 가능하다면 실행합니다.
만약 스코프에서 식별자를 찾지 못했다면 참조 에러(ReferenceError)를 출력하고, 식별자는 찾았지만 실행할 수 없는 타입이라면 타입 에러(TypeError)를 출력합니다.
not(); // ReferenceError: not is not defined
var foo = 'some';
foo(); // TypeError: foo is not a function
-> 실행 컨텍스트 : 코드를 실행하기 위해 필요한 환경으로 실행할 코드에 제공할 환경정보를 모아놓은 객체. 어떤 실행컨텍스트가 활성되는 시점에서 선언된 변수들을 위로 끌어올리고(호이스팅) 외부 환경 정보를 구성하고, this 값을 설정하는 등 동작 수행. 이로 인해 다른 언에서 발생할 수 없는 특이한 현상이 발생한다고 한다.
-> 콜 스택 : 콜은 말 그대로 호출. 스택은 마치 출입구가 하나인 우물 같은 구조. 콜스택은 자바스크립트가 함수 호출을 기록하기 위해 사용하는 우물 형태의 데이터 구조. 즉 맨 위에 놓인 함수부터 우선 실행
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
1) 첫번째는 첫 콘솔로그, 두 번째는 함수 안에 콘솔, 세번째는 두 번째 콘솔로그
2) a는 함수 스코프 내에서 정의되어 있으므로 콘솔이 찍히지 않는다.
1 == "1";
1 === "1";
-> ===는 자료형을 보기 때문에 False고 ==는 자료형을 안 보기 때문에 True가 뜰 것이다.