DOM (Document Object Model)
브라우저가 HTML 문서를 파싱하는 과정에서 생겨나는 객체
Tree구조로 생기게됨.
전역 스코프 (global scope)
문서 전체에서 참조 할 수 있음.
지역 스코프 (local scope)
함수와 같은 범위 내에서만 참조가 가능함.
함수 레벨 스코프
const sum = function(){
var x = 0;
}
console.log(x);
var 로 선어된 키워드가 함수 레펠 스코프안에 존재하기 때문에 함수 밖에서 호출 할 시
undefined error 가 발생함.
블록 레벨 스코프
if(){
var y = 0;
}
console.log(y)
if문이나 for문을 실행 할 시에도 {}를 사용하는 데 이경우는 블록 레벨 스코프라고 한다.
이 경우 var 로 선언된 키워드는 블록 레벨 스코프를 따르지 않기 때문에
블록 밖에서 호출 할 때에도 정상적으로 값이 호출 된다.
❗️ 그래서 var 로 선언하는 것을 자제해야함.
📌 var는 함수 레벨 스코프는 따르지만, 블록 레벨 스코프는 따르지 않는다.
📌 let은 함수 레벨 스코프와 블로 레벨 스코프를 둘다 따름.
해당 스코프에 변수가 없을 시 상위 스코프로 타고타고 올라가서 변수를 찾는 것
console.log(letKeyword);
let letKeyword = `let is safe`
console.log(varKeyword);
var varKeyword = 'var is not safe';
위의 let
의 경우 letKeyword가 선언되기 이전에 호출되었기 때문에,
아예 오류가 나면서 코드 실행이 중단됨.
아래의 var
의 경우 varkeyword가 선언되기 이전에 호출되어도 undefined 형식으로 출력 해줌 -> 이렇게 되면 에러를 미연에 방지 할 수 없음.
자바스크립트는 코드를 실행하기 이전에 한번 해석하는 과정을 거친다.
해석하는 과정을 거친 뒤 컴퓨터에게 전달하기 위해 재배열하는 과정을 거친다.
자바 스크립트가 코드를 실행 할 때는 이렇게 해석해서 동작
console.log(letKeyword);
let letKeyword = 'let is safe;
var varKeyword;
conosole.log(varKeyword);
varKeyword = 'var is not safe';
이렇기 때문에 var
키워드 사용을 지양하고, let, const
사용을 지향해야함.
fn1();
function fn1(){
console.log("hoisting occurred")
}
//return : hoisting occurred
함수를 선언식으로 작성한 경우 문제없이 잘 동작함.
fn2()
const fn2 = function(){
console.log("error occurred")
}
함수를 표현식으로 작성한 경우 에러가 발생.
변수의 선언 단계
선언 -> 초기화 단계 -> 할당단계
ex) let test = 1;
선언 단계 : 변수명이 객체에 담기는 단계 여기서는 test가 담기는 형태
초기화 단계: 변수에 할당할 메모리 공간을 부여하는 단계
할당 단계 : 정의된 변수에 데이터가 할당되는 단계
console.log(letKeyword); // 에러
let letKeyword = 'let is safe'
console.log(constKeyword); // 에러
const constKeyword = 'const is safe'
let
const
는 해당 코드 라인에 도달하기 전에는 TDZ(Temparal Dead Zone)에 존재하기 때문에 위의 코드는 에러가 발생하는 것.
** 호이스팅이 발생하지 않는 것은 아님.
var
키워드의 경우 선언단계와 초기화단계가 같이 존재하기 때문에 TDZ가 존재하지 않음.
const fn = function(){
console.log("TDZ의 영향을 받는다")
}
함수 표현식도 마찬가지로 TDZ의 영향을 받기 때문에, 해당 코드도 에러가 발생한다.
함수 선언식도 var
키워드와 동일하게 작동하기 때문에, 함수가 어디에 존재하든 실행된다.
: 구조화 되어 있는 배열, 객체와 같은 데이터를
destructuring(분해) 시켜, 각각의 변수에 담는 것
배열의 구조분해 할당
let arr = [1,2];
let [ one, two ] = arr;
객체의 구조분해 할당
let obj = { name: "other" , gender: "male"}
let { name, gender } = obj;
// key값으로 변수명을 하고 싶지 않을 때
let { name: newName, gender: newGender } = obj
// 배열
let arr = [1,2,3,4,5]
console.log(...arr) // 1,2,3,4,5
//문자열
let str = "Hello"
console.log(...str); // H e l l o
//객체
let obj = { name: "otter", gender: "male"}
const newObj = obj;
newObj.name = "rabbit"
console.log(newObj.name) // rabbit
console.log(obj.name) // rabbit
이 경우 obj와 newObj는 데이터가 아닌 주소를 할당 받은 거기 때문에 똑같은 객체를 바라보게 되는 것.
이걸 해결하기 위해서는 밑의 방식으로 하면됨.
let copyObj = {...obj};
copyObj.gender = female;
console.log(copyObj.gender) //female
console.log(obj.gender) //male
obj.hobby = { one : "play", two: "watch"}
copyObj = {...obj}
copyObj.hobby.two = "sleep"
console.log(copyObj.hobby.two) // sleep
console.log(obj.hobby.two) //sleep
객체안에 객체가 또 있는 경우에는 제대로 동작하지 않음.. 이런 방법을
얕은 복사
라고 함
얕은 복사
주소값 까지만 복사하는 얕은 복사
위의 스프레드 연산쪽 코드의 부연설명으로 그림을 보면
이런 과정을 거치기 때문에, 얕은 복사기 되어버림.
깊은 복사
실제 데이터까지 복사하는 싶은 복사
let origin = {
name: "otter",
age : 25,
favaoriteFood : {
first: "hamburger",
second: "pizza"
}
}
const copy = JSON.stringify(origin);
const deepCopy = JSON.parse(copy);
실제 원시 데이터가 존재하는 곳을 Heap메모리
라고 한다.
let origin = {
name: "otter",
age : 25,
petName: "cherry",
hobby: "playing game"
}
const {petName, hobby, ...rest } = origin
console.log(rest) // {name : "otter, age: 25}