FrontEnd/인간 JS 엔진되기

1. 함수호출 스택 , 스코프 체인 , 호이스팅 , this

Tony Lim 2022. 6. 1. 11:44

함수 호출 스택 분석

가장 바깥은 anonymous 가 호출 된다 그 이후 차례대로 코드에 적힌 함수 호출

 

스코프 체인 

ES2015 부터 scope 는 이제 블록{} 단위이다. 원래는 function 단위였다고 함

const x = "x";
function c() {
    const y = 'y';
    console.log(c);
    function b() {
        const z = 'z'
        console.log('b')
    }
}

function a() {
    const x= 'x';
    console.log('a');
    b();
}

a();
c();

scope 분석을 해보자 == lexical scope , 한번 코딩 해놓으면 scope는 바뀌지 않음

c -> anonymous

a -> anonymous

b -> c-> anonymous

이걸 기반으로 mapping을 해보자

anonoymous -> {x,c,a}

c -> {y,b}

b ->{z}

a -> {x}

이때 a에서 b가 접근이 가능한가? 

1. a scope에서 b를 찾을수 있는가? -> x 밖에없다. 못찾음

2. a 의 부모 scope 인 anonymous 에서 b를 찾을 수 있는가? -> x,c,a  가 있다. 못찾음

그럼 b에서 a 접근이 가능한가?

위와 동일하게 b scope 먼저 확인 -> 없음 -> anonymous scope 확인 x,c,a 존재함 찾음 -> 접근 가능 (호출 가능)

 


 

호이스팅

발동이 안되게 하는것이 가장 좋다.

var, function 은 다 맨위로 올라가 진다. let ,const 는 그렇지 않음

function c() {
    function b() {
        a();
    }
  b();
}

c();

function a() {
    console.log("worked");
}

b -> c-> anonymous

a -> anonymous

mapping을 하면

anonymous -> {b, a}

c -> {b}

a -> {}

b -> {}

b의 scope에 a가 있나 ? -> 없음 -> 부모인 c scope 에 a 선언이 있나? -> 없음 -> 부모인 anonymous scope 에 있나? a가 존재함 이떄 

const a = () => { console.log('a') }

이런 식으로 존재할 경우 호이스팅이 되지 않아 undefined 가 뜨게 된다. 

선언은 다 맨위에서 하자

 


 

this

일반 function 안에서 선언된 this는 해당 함수가 호출되는 시점에서 this가 결정이 된다.

arrow function의 경우에는 자신의 부모 scope가 this 가 된다. 

const obj = {
    name: 'tony',
    sayName() {
        console.log(this.name)
    }
}

obj.sayName()
// tony

const sayN = obj.sayName
sayN()
// window.name 이 호출되게 된다.
function Human(name) {
	this.name = name;
}

new Human('tony')
// this 가 객체 자기자신을 가르킴

this 가 바뀌는 경우 1. new 를 통해 호출하거나  2. obj.sayName 처럼 앞에 객체가 붙는 경우 바뀐다.

 

function sayName() {
    console.log(this.name)
}

sayName();
//this == window

sayName.bind({name:'tony'})
sayName.apply({name:'tony'})
sayName.call({name:'tony'})

this를 bind할 수 있다. apply,call은 bind하고 호출 까지 하는것이다. 

https://stackoverflow.com/questions/1986896/what-is-the-difference-between-call-and-apply

 

What is the difference between call and apply?

What is the difference between using Function.prototype.apply() and Function.prototype.call() to invoke a function? var func = function() { alert('hello!'); }; func.apply(); vs func.call(); Are ...

stackoverflow.com

 

const obj = {
    name: 'tony',
    sayName() {
        console.log(this.name)
        function inner() {
            console.log(this.name);
        }
        inner();
    }
}
obj.sayName()
// obj.name = tony
// window

inner는 호출하는 시점에 new, object 같은것이 앞에 붙어서 호출된게 아니다. 그래서 this 가 window로 바뀌지 않는다.

const obj = {
    name: 'tony',
    sayName() {
        console.log(this.name)
        const inner = () => {
            console.log(this.name);
        }
        inner();
    }
}

obj.sayName()

이 arrow function인 경우에는 부모 scope의 this를 가져오게 된다.

부모의 this == obj 이것을 그대로 가져오게 되어 tony가 호출된다.

만약 부모가 호출을 안당했으면 inner의 this 는 모르는것이다.

 

header.addEventListener('click',function() {
    console.log(this)
})

이 경우 this 가 뭔지 알수가 없다. (header로 나오지만)  anonymous function 은 호출된적이 없다. 호출된건 addEventListener 함수이다.

하지만 예측을 해보면

const header = {
    addEventListener: function(eventName , callback) {
        callback.call(header);
    }
}

이런식으로 this를 header로 맵핑해줬을것이라고 예상해볼수 있다.

'FrontEnd > 인간 JS 엔진되기' 카테고리의 다른 글

2. promise ,async await , closure  (0) 2022.06.04