본문 바로가기

programming/Javascript

[Javascript] 함수선언문 & 함수표현식 & 화살표함수()=>{} 비교(호이스팅, this 관점에서)

호이스팅 관점에서의 차이

함수선언문은 함수 자체가 호이스팅 된다.

함수표현식은 함수 자체는 호이스팅 되지 않고, 변수가 호이스팅된다.

화살표함수는 함수표현식의 다른 표현(ES6에서 추가)으로 마찬가지로 함수는 호이스팅 되지 않고, 변수만 호이스팅된다.

선언하고, 사용하는게 정상적 로직이므로 함수표현식&화살표함수를 권장한다.

 

case1) 함수 선언문은, 런타임 이전에 엔진에서 먼저 실행되어서 함수 자체를 호이스팅 한다.

console.dir(plus) // output: ƒ plus(x, y)
console.log(plus(2, 5)) // output: 7

// 함수 선언문
function plus(x, y) {
	return x+y
}

 

case2) 함수 표현식은 런타임 이전에 변수에 undefined라고 초기화만 시켜두고, 런타임에서 객체가 된다.

console.dir(sub) // output: undefined
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function

// 함수 표현식 예시
var sub = function(x, y) {
    return x + y
}

 

case3) 화살표함수는 런타임 이전에 변수에 undefined라고 초기화만 시켜두고, 런타임에서 객체가 된다.

console.dir(sub) // output: undefined
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function

// 화살표 함수 예시
var sub = () => {
    return x + y
}

 

this 관점에서의 차이

 

- 화살표함수는

this 가 없다. 자기만의 this 가 없다. 이 this 를 찾을때 자기 스코프 안에서 없으면, 함수가 실행되는 위치에서 스코프를 뒤져본다. (스코프 체인 순서대로 뒤진다) 

bind, apply, call 사용불가

(참고) 이름도 없다. 익명함수 / arguments도 없다

 

- 함수선언문에서 

this의 값은 함수를 호출하는 방법에 의해 결정된다.

 

case1) 함수선언문에서 다른 호출방법에 의한 this

// 호출하는 방법에 따라 결정된다.
var someone = {
    name : 'Mike',
    who : function(){
        console.log(this)
    }
}

// 호출방법1 -> 누가호출했니? someone
someone.who();

var myWho = someone.who;
// 호출방법2 -> 누가호출했니? global(브라우저)
myWho();

 

case2) 함수선언문과 화살표함수에서의 this

-> 같은 결과를 냈지만, 함수선언문에서는 함수를 호출하는 방법에 의해 this 가 결정되기 때문에, global(브라우저) 가 불렀기 때문에 window 를 리턴한다.

화살표함수는 자체 this 가 없기 때문에, 스코프 체인 순서대로 this 를 찾는다. 가장 밖에 있는 global(브라우저)가 리턴된다.

// 함수선언문
function who() {
    console.log(this)
}

who()

// 화살표함수
const when = () =>{
    console.log(this)
}

when();

 

 

case3) 함수선언문은 누가 호출했는지 확인하여 someone을 this로 받아서 age를 잘 리턴하지만, 화살표함수는 자체 this 가 없기 때문에 스코프 체인에 의해 window로 올라가서 name을 찾으니 없어서 안나온다.

let someone = {
    age : 10,
    name : 'Mike',
    LogAge : function() {
        console.log(this.age);
    },
    LogName : ()=>{
        console.log(this.name)
    }
}

someone.LogAge();
someone.LogName();

 

 

case4) 함수선언문 안에!

함수선언문으로 버튼에 클릭 이벤트를 단 경우, -> 누가 호출했나? -> button 이 호출했다 -> this 는 button

함수선언문으로 버늩에 클릭 이벤트를 달고 + this 를 bind 한 경우 -> this 를 someone으로 묶어준다

화살표함수로 버튼에 클릭 이벤트를 단 경우, -> 화살표 함수는 this 가 없으니까, 스코프 체인에 의해 상위의 함수 선언문안에 있는 this 가 리턴되어, gender 값을 가져올 수 있다.

 

let someone = {
    age : 10,
    name : 'Mike',
    gender : 'Female',
    LogAge : function() {
        btn.addEventListener('click', function(){
        	console.log(this)
            console.log(this.age)
        })
    },
    LogName : function() {
        btn2.addEventListener('click', (function(){
            console.log(this.name)
        }).bind(this))
    },
    LogGender : function() {
        btn3.addEventListener('click', ()=> {
            console.log(this.gender)
        })
    },
    
}