Section 3. context, hoisting, scope, this, IIFE
Udemy - JavaScript: The Advanced Concepts
Section 3. Foundation 2
실행 컨택스트(Execution Context)
call stack 쌓기
- JS엔진은 처음 실행시 전역실행컨텍스트를 생성하여 call stack에 쌓는다.
- 함수가 호출될때마다 새로운 실행컨텍스트를 생성하여 call stack에 쌓는다.
(변수: {variable,arguments}, this, scope chain) - 함수가 끝나면 call stack에서 해당함수의 실행컨텍스트를 제거한다
실행 컨텍스트
- 생성단계 - Hoisting
1) Lexical Environment (변수 let, const - uninitialized)
2) Variable Environment (함수선언, 변수 var - undefined)
3) this - 실행단계
Lexical Environment & Variable Environment
- VE는 LE를 상속하기 때문에 둘다 LE라고 말할수 있다
- hoisting, scope의 차이 때문에 구분지어 사용
Lexical Environment
- Environment Record: 내부에서 선언된 데이터 + arguments객체
- Outer Environment Reference (Scope Chain) : 현재 렉시컬 환경에서 찾을수 없는 변수들을 상위 렉시컬 환경을 타고올라가면서 탐색
lexical scope : 함수 선언 위치 기준
<-> Dynamic Scope : 함수 호출 위치 기준
var x = 'global';
function a() {
console.log(x);
}
function b() {
var x = 'b';
a();
}
b(); // console.log(x) -> global
// a
// b x='b'
// global x='global'
//콜스택에 함수의 실행컨텍스트는 위와 같이 쌓였지만
//호출 위치에 상관없이, 선언위치 기준으로 scope chain에서 x를 찾음
Hoisting
변수는 선언부, 함수는 전체가 끌어올려짐 (const, let 은 좀 다름)
실제로 코드를 옮기는 것은 아니고, 시작전에 메모리에 할당하는것을 뜻함
// 변수는 첫번째 a가 선언되고, 두번째 a는 무시. 그리고 코드진행하면서 차례대로 값 대입
console.log(a) //undefined
var a = 1;
console.log(a); //1
var a = 2;
console.log(a); //2
// 함수는 첫번째 b가 선언+할당 되고, 두번째 b가 덮어쓰기. 그리고 코드진행.
b(); //4
function b (){ console.log("3") }
b(); //4
function b() {console.log("4")}
b(); //4
var, const, let 선언 없이 그냥 쓰는경우
함수 안에서 사용해도 전역변수에 생성됨
arguments 사용 주의 : 아래와 같이 쓰는걸 권장
1) Array.from(arguments)
2) arguments.length
3) arguments[i]
4) function foo (...args) {... args를 대신사용...}
Function Scope(var) vs Block Scope(const/let)
초기 JS는 Function Scope 사용 (var)
ES6에서 Block Scope사용하도록 기능 추가 (const, let)
if (5 > 4) {
var a = 'a';
const b = 'b';
let c = 'c';
}
console.log(a); //a
console.log(b); //error
console.log(c); //error
for문에서의 var/let
for (var i = 0; i < 5; i++) {
console.log(i)
}
console.log(i);
// 0, 1, 2, 3, 4 출력
// 5 출력
for (let i = 0; i < array.length; i++) {
console.log(i)
}
console.log(i);
// 0, 1, 2, 3, 4 출력
// error!
함수 용어
function india() {...} //함수 선언식(Declaration)
var canada = () => {...} //함수 표현식(Expression)
canada(); //함수 Invocation/Call/Execution
IIFE
Immediately Invoked Function Expression
전역변수를 줄이기 위한 방법중 하나 (ES6 이후에는 모듈 사용)
(function(){})(); //함수 표현식은 바로 실행 가능
function(){](); //함수 선언식은 바로 실행 불가
var script1 = (function(){
function a = {
return 5;
}
return { a };
})();
script1.a(); //전역환경에 script1하나만을 더해 새로운 환경을 만들었다
이게 잘 활용된 예는 jQuery
jQuery는 수많은 기능이 있지만, window.$, window.jQuery 하위에 모두 담고있음
그래서 $('h1')처럼 $로 접근
for (var i = 0; i < 5; i++) {
setTimeout(function(){
console.log(i)
}, 1000)
}
//5,5,5,5,5
for (var i = 0; i < 5; i++) {
(function(j){
setTimeout(function(){
console.log(j)
}, 1000)
})(i)
}
//0,1,2,3,4
이런경우에도 유용하다
this
- 객체, 함수를 속성으로 가진
- x.someFunc > x가 this
- window.aFunc > window - dynamic scope 사용 (헷갈릴수있음 중요!!)
Lexical Scope(기본) vs Dynamic scope(this)
var name = 'in global';
function print() {
console.log(name); //함수의 위치 기준 -> in global
console.log(this.name); //함수의 호출 기준 -> in Obj
}
var obj = { name: 'in Obj', print: print}
obj.print();
헷갈리는 this를 잘 사용하기 위한 방법
- 화살표 함수는 lexical scope를 사용함 (ES6부터 사용)
- this를 변수에 담아 사용
- 함수.bind(this, parameter나열 1, 2, 3...) - 함수 반환
- 함수명.call(this, parameter 나열 1, 2, 3,...) - 즉시실행
- 함수명.apply(this, [parameter 배열]) - 즉시실행
const obj = {
name: 'Billy',
sing: function() {
console.log(this)
var basic = function() { console.log(this); }
var arrow = () => console.log(this);
var self = this;
var smart = function() { console.log(this); }
var bindedBasic = basic.bind(this);
basic(); // global (함수 선언위치가 아닌 호출위치 기준)
arrow(); // obj (화살표 함수는 lexical scope 사용)
smart(); //obj (변수는 lexical scope 사용)
bindedBasic(); //obj
basic.call(this); //obj
basic.apply(this); //obj
}
}
obj.sing() // obj
bind의 재밌는 사용법
function multiply(a, b) {
return a*b;
}
var multipleByTwo = multiply.bind(this, 2);
console.log(multipleByTwo(4));
var multipleByThree = multiply.bind(this, 3);
console.log(multipleByThree(4));
apply의 재밌는 사용법
const array = [1,2,3];
function getMaxNumber(arr){
return Math.max.apply(null, arr);
}
getMaxNumber(array)
this의 4가지 해석방법
- 암시적 사용 : 호출하는 객체가 this (dynamic scope)
- 명시적 사용 : .bind() 로 this 지정
- new : 클래스의 인스턴스가 this
- 화살표 함수 : 선언 위치의 this (lexical scope)
'use strict'
- 초기에 JS 가 완벽하진 않았음
- 그래서 발생할 수 있는 실수를 막아줌
- ES6에서는 자동으로 포함되어있음
읽기 목록
LE, VE의 공통점과 차이점까지 나누어 상세하게 설명 :
https://dkje.github.io/2020/08/30/ExecutionContext/
클로저 상황의 실행컨텍스트까지 설명 :
https://www.zerocho.com/category/JavaScript/post/5741d96d094da4986bc950a0
Author And Source
이 문제에 관하여(Section 3. context, hoisting, scope, this, IIFE), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@dldngus5/Section-3-context-hoisting-scope-this-IIFE저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)