상세 컨텐츠

본문 제목

[Javascript] 변수, 상수, 데이터 타입, 호이스팅, 스코프 체인

😎 지식/FE-리액트🌐

by :Eundms 2021. 9. 9. 23:33

본문

 선언과 정의 

javascript는 선언과 정의가 동일하다.

왜? var x;만해도 undefined가 들어가기 때문에

 

 function scope vs block scope 

var - function scope

let - block scope

const - block scope

function fbScope(){ // var v = 1;
	const t = rue;
    if (t) { // const x = 3;
    	console.log('inside if block');
        var v = 1; //blcok 내에서 선언되었지만, 함수 scope 이기에 (함수내 hoisting)
        const x = 3;
        console.log(v,x);
    }
    console.log(typeof v, typeof x); // number undefined
}
fbScope();

 

 Scope와 존재 

동작 측면 Scope (정적 vs 동적)

레벨 측면 Scope (전역/지역 vs 함수/블럭)

변수는 스코프 내에 존재한다!

var x = 1; //전역
console.log('x>>',x);

function printX(){
	console.log('printX >',x); 
}

function main(){
	var x = 2; //지역,함수 스코프
    printX();
}

main(); // 정적 : 1(javascript), 동적 : 2

 

버튼1 버튼2 버튼3 버튼4

버튼1~4에 이벤트 리스너를 단다고 하자/

document.addEventListener('DOMContentLoaded',()=>{
	/*var i =0 */
    console.log("document's ready");
    
    for (var i = 0 ; i< 5; i+=1){
    	document.getElementById(`span${i+1}`).addEventListener('click',()=>{
        	console.log(i+1);
        });
    }
});

//버튼 1~4가 각각 클릭되었을 때, 모두 6이 찍힘 
// 왜? var는 function Scope이기에 function의 맨위에 var  i = 0으로 해 놓은 것이랑 동일한 의미가 됨.
// => for (let i =0;...)으로 바꿔야 함.

 호이스팅(hoisting)과 Scope Chain 

hoisting (var, function=>함수 스코프 내에서 |  let, const=> 블록 스코프 내에서)

- 평가 단계에서 선언문을 만나면 끌어 올린다!

- JS는 정적 스코프이다!

scope chain (가시성 visibility)

- 외부에서 내부 함수의 변수는 접근 불가!

console.log('x1 >>', x); //x1 >> 1
x = 1;
var x; //제일 첫번째 줄에 선언한 거랑 동일
console.log('x2 >>', x); //x2 >> 1
f1(); // hositing되어서 에러 없이 실행된다.

// scope chain
function f1() {
    console.log(y); //y는 f2속에서 아직 존재하지 않기에 접근할 수 없다.
    function f2() {
    	var y = 2;
        function f3() {
        	console.log(y); 
        }
        f3();
    }
    f2();
}

 데이터 타입 (Primitive vs Object) 

원시 (Primitive , Immutable) 타입 : call by Value

let n = 2; // n의 주소 : &1 , &1에 들어있는 값 : 2 
n = 5; // n의 주소 : &2 , &2에 들어있는 값 : 5

let m = 5; // m의 주소 : &5, &5에 들어있는 값 : 5


/*
만약, n===m 을 물어보면!
1) m의 값(&5의 값)인 5를 가져온다
2) 비교한다
*/

 

Object (Mutable) 타입 : call by Reference

a1 = [1,2];  // 시작주소 : &10  (heap공간에 저장해놓고 이를 가리키는 포인터를 저장해놓는)

a2 = [1,2];  // 시작주소 : &30

a1 === a2 //주소로 비교하게 되니까

a1=a2 

a1 === a2 //위의 연산으로 주소가 같아짐.

 

명시적 타입 변환 vs 암묵적 타입 변환

const n = 1; arr = [1,2];
n.toString(), arr.toString(); 
(NaN).toString(), (Infinity).toString()
x = Number(s);
x = String(s);
parseInt(s); // parseInt('18.8cm')
Boolean('false'), Boolean({}), Boolean([]), Boolean(1)
Boolean(''), Boolean(NaN), Boolean(null), Boolean(0)

var a; //a에는 undefined가 들어가 있음. 메모리 칸은 잡혀있지만, 어떤 값이 있을지 모름

var a = null // a 값을 싹 비워라

s = n + '';
2 - '1'  //1
2 + '1' //"21"
2 * '10' //200
'1' > 0 //true
+true // 1
+false // 0

일시적 객체로의 변환

primitive가 object로 1에서 잠시 변했다가 (s 원래 string이었음) 

2에서는 다시 primitive로 돌아옴


Primitive(원시) 타입이 immutable인 이유? 

a=3; //a : &1

a=10; // a : &2

과정에서 생각해보면 3이 있는 주소 &1의 값이 10으로 바뀌는 것이 아니고,

10이 있는 주소 &2를 새로 하나 만들고,

a의 주소가 &2로 바뀌는 것이다. (immutable)

 

> s= "abc"에서 s="abcdef......."로 바꿀 때, 연속적으로 데이터가 위치해 있을 수 없음.

링크드리스트로 계속 찾아가는 작업을 해야 함.

그냥, 빈 공터에 abcdef...를 하나 만들고 그 주소를 s로 하는 게 효율적.

그리고 사용하지 않는 'abc'는 가비지 컬렉터가 처리

 

Object 타입이 mutable한 이유

> 시작주소만 가지고 있다. 시작주소가 가리키는 값의 내용이 변경됨.(heap에 저장 여유가 있음)

 

CPU (캐시), Memory(힙의 위치)

u={id:1,name:'a'}

u.abc='abbc' // 힙에서 가져옴.


자바스크립트에서 null과 undefined의 메모리 할당

var a; // 선언, 정의
var a = 2;
int i; // 선언 (undefined)
a = null; // &100
abc; def;  
s = 'str' //get until null point

cf) mysql에서 varchar(7)이렇게 해놓으면 7자리글자쓰고 나머지 1byte는 널 포인트가 들어가서

8byte씩 끊어서 사용하는 것에 최적화가 될 수 있다. 예를들어, 8자리보다 크다면 varchar(15)

예전에는 이렇게 했다~ 빈공간을 줄이기 위해서,


 Hoisting 

- 변수 hoisting

- 함수 hoisting : 함수 선언문 / 함수 표현식

a=1;
function f1(){....}
const f2=function(){....}
var a;

함수형 언어평가 -> 실행하기에

함수형 언어는 평가 단계컴파일이구나

const 소중한 문장. const를 let으로 하는 순간. 

 

관련글 더보기

댓글 영역