이번에 면접 대비를 위해 프론트 엔드 분야에서 알아야 될 내용들을 정리하고자 합니다.
➡️ 함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것. 끌어올린다고 생각하면 됩니다.
여기서 유효 범위는 함수 블록 {}
안을 뜻합니다.
✅ 자바스크립트에서는 ES6에서 도입된 let, const를 포함한 모든 선언을 호이스팅합니다.
변수는 3가지 단계를 거쳐 생성 됩니다.
초기화 단계(Initialization Phase): 변수 객체(Variable Object)에 등록된 변수를 위한 공간을 메모리에 확보합니다. 이 단계에서 변수는 undefined
로 초기화됩니다.
할당 단계(Assignment Phase): undefined
로 초기화된 변수에 실제 값을 할당합니다.
💡 var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어집니다.
➡️ 초기화 단계에서undefined
로 초기화되기 때문에 변수 선언문 이전에 변수에 접근해도 에러가 발생하지 않고undefined
를 반환하는 것입니다.
💡 반면 let, const 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 이루어집니다.
➡️ 따라서, 스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어지므로 초기화 이전에 변수에 접근하면 참조 에러(ReferenceError)가 발생하는 것입니다.
스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 일시적 사각지대(Temporal Dead Zone, TDZ)라고 합니다.
calculateAge(1999); // 함수 선언 전에 함수를 호출 -> hoisting 이 되어 잘 작동한다.
function calculateAge(year){ // 함수 선언.
console.log(2020 - year);
}
//retirement(1990); // 작동하지 않는다
var retirement = function(year) { // 함수의 선언 방식이 아니기 떄문에 hoisting 되지 않는다. (only work on function declaration)
console.log(65- (2020- year));
}
//variables (변수)
console.log(age); // 작동은 되지만 undefined로 뜬다. (hoisting) -> js 가 변수가 선언되었는지는 알고 있는 것이다.
// 변수의 선언만 호이스팅.
var age = 50; //global
console.log(age);
function foo(){
var age = 65; //local
console.log(age); //local print
}
foo();
console.log(age); // global print
➡️ 변수 선언이 함수 선언보다 높은 우선순위를 가집니다.
var myName = "hi";
function myName() {
console.log("yuddomack");
}
function yourName() {
console.log("everyone");
}
var yourName = "bye";
console.log(typeof myName); // string
console.log(typeof yourName); // string
✅ 두 개의 함수로 만들어진 환경으로 특별한 객체의 한 종류
-> 외부 함수 호출이 종료되더라도 외부 함수의 지역 변수 및 변수 스코프 객체의 체인 관계를 유지할 수 있는 구조를 클로저라고 합니다.
++ 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수
var color = 'red';
function foo() {
var color = 'blue'; // 2
function bar() {
console.log(color); // 1
}
return bar;
}
var baz = foo(); // 3
baz(); // 4
-> 여기서 baz가 클로져입니다.
outer
함수의 context에 속해있는 변수를 참조합니다. outer
함수의 지역변수로 존재하는 color
를 자유변수라고 합니다. 전역 변수의 사용 억제 => 자신이 생성되었을 때의 lexical 환경을 기억하기 때문이다.
정보의 은닉
참고 : https://poiemaweb.com/js-closure
✅ 자바스크립트에서 모든 함수는 실행될 때마다 함수 내부에 this라는 객체가 추가됩니다.
✅ this는 함수가 호출되는 상황에 따라서 달라집니다.
객체의 프로퍼티가 함수일 경우에는 메서드라고 합니다.
var myObject = {
name: "foo",
sayName: function() {
console.log(this); // 여기서 this는 myObject를 참조
}
};
myObject.sayName();
// console> Object {name: "foo", sayName: sayName()}
➡️ 메서드에서 this
는 메서드를 포함하고 있는 객체를 참조합니다. (해당 메서드를 호출한 객체가 바인딩 되는 것)
✅ 객체의 메서드가 아니라 함수를 호출하면 this
는 전역 객체에 바인딩됩니다.
var value = 100;
var myObj = {
value: 1,
func1: function() {
console.log(`func1's this.value: ${this.value}`);
var func2 = function() {
console.log(`func2's this.value ${this.value}`);
};
func2();
}
};
myObj.func1();
// console> func1's this.value: 1
// console> func2's this.value: 100
func1
은 myObj 객체의 메서드이기 때문에 this
에는 myObj
가 바인딩 된다.
func2
는 메서드가 아닌 함수이기 때문에 this
에는 전역 객체가 바인딩된다.
✅ new 키워드를 통해서 생성자 함수를 호출할 때는 this
는 객체 자신이 됩니다.
✅ new를 사용하면 빈 객체가 생성되는 것입니다.
let Person = function (name, year, job) {
this.name = name;
this.year = year;
this.job = job;
console.log(this);
};
var john = new Person("hi", 1996, "hoho"); // new 를 통해서 새로운 빈 object 가 생성된 것이다. 그리고john 에 할당해주는 것이다.
var Person = function(name) {
console.log(this);
this.name = name;
};
var foo = new Person("foo"); // Person
console.log(foo.name); // foo
➡️ bind 는 함수가 가리키는 this 만 바꾸고 호출하지 않음. (this 를 고정시킨다)
➡️ call 은 this를 바인딩하고 함수를 호출하고 실행시킨다. (this 를 설정해줄 수 있다)
➡️ apply 는 call과 거의 똑같지만 인자 전달을 배열로 해준다.
var john = {
name: "heeje",
age: 25,
job: "student",
presentation: function (style, day) {
if (style === "formal") {
console.log(
"good moring" + day + "i'm " + this.name + this.job + this.age
);
} else if (style === "friendly") {
console.log("hey what's up?" + this.name + this.job + this.age);
}
},
};
john.presentation("formal", "morning");
var jane = {
name: "jane",
age: 25,
job: "pro",
};
john.presentation.call(jane, "friendly", "afternoon"); // call method (jane 을 전달. this를 바인딩 )
// => john.presentation.apply(jane, ["friendly", "afternoon"]);
let johnFriendy = john.presentation.bind(jane); //bind method -> this를 jane 으로 변경 -> 함수를 실행하지 않는다.
johnFriendy("friendly", "moring");
앞으로의 면접 준비를 위해서 글을 정리해보았습니다.
let/const도 호이스팅이 이루어집니다. 다만 선언과 초기화가 나누어져있어서 TDZ으로 인해 에러가 발생하는거죵
https://wonism.github.io/is-let-hoisted/