top bar

글 목록

2017년 7월 16일 일요일

[Javascript] 함수 호출 방법과, this 스코프의 설정

개요



오늘은 자바스크립트에서 함수를 호출하는 방식을 정리하려고 한다.

각각 함수호출 방법과 그 방법을 사용할때 'this' 객체는 서로 상이하기 때문에, 잘 알아두고 사용해야 유효범위(이하 '스코프')의 혼란을 예방할 수 있다.


함수는 '객체'다



놀랍게도 자바스크립트 에서의 함수는 '객체' 다. 정확히 말하면 값으로 취급 될 수 있는 '1급 객체' 다. 이 말 뜻은, 함수 자체에도 속성을 가질 수 있다는 것이며, 그 속성은 또 다른 함수가 될 수 있다는 말이다.

따라서 함수는 아래와 같이 '그냥' 호출 할 수도 있지만,

function func() {
    // do something
}

func();

아래처럼 함수 객체의 속성 메서드인 'call', 'apply', 'bind' 로도 호출 될 수 있다.

func.call(...);
func.apply(...);
func.bind(...);


함수 호출과 'this'



1) 기본

아래처럼 일반 함수 호출에서의 'this' 는 'window'(머리객체) 이다. ('nodejs'의 경우는 'global')

function func() {
    console.log(this); // window
}

하지만 'use strict' 를 사용하면 undefined 이다.

function func() {
    'use strict'
    console.log(this); // undefined
}


2) 객체 속성 으로서의 함수

하지만 객체에 속한 '메서드' 라면, 얘기가 조금 달라진다.
아래에서 'this' 는 객체 자신이다.

const someone = {
  name: 'Someone',
  sayHello: function(otherName) {
    console.log(this.name + ' says hello to ' + otherName);
  }
};

someone.sayHello('thomson'); 
// 결과 > 'Someone says hello to thomson'


하지만 위에서 언급한 call, apply 메서드를 사용하면, 첫번째 파라메터로 전달되는 객체를 해당 함수 스코프에서의 'this' 로 할당 할 수 있다. 아래와 같다

const alex = {
    name: 'Alex'
};

someone.sayHello.call(alex, 'thomson'); 
// 'Alex says hello to thomson'

someone.sayHello.apply(alex, ['thomson']); 
// 'Alex says hello to thomson'

첫번째 파라메터로 'alex' 객체를 넘겨주었다. 때문에 'sayHello' 메서드 내부의 'this'는 'alex' 객체이다.
따라서 위와 같은 결과가 출력된다

하지만 'bind' 메서드는, 위의 call이나 apply와는 조금 다르게 동작한다.

const bound = someone.sayHello.bind(alex, 'thomson'); 
bound();
// 'Alex says hello to thomson'

'bind' 메서드는 특정 함수의 'this'와 파라메터를 설정한 뒤, 해당 함수를 반환한다.
따라서 bound() 와 같은 방식으로 파라메터를 넘기지 않고 호출해도 call, apply와 같은 결과가
출력 되는 것이다.

또 한가지, bind 메서드는 아래와 같이도 동작한다.

function func(x, y) {
    return x + y;
}

const bound = func.bind(null, 10);
console.log(bound(20)); // 30

bind 메서드의 첫번째 파라메터로 특정 객체를 함수 내부의 this 로 설정할 수 있지만 위의 예제에선 필요 없으므로 'null' 을 넘겼다. 그리고 두번째 파라메터로 10을 넘겼는데, 이는 'func' 함수의 첫번째 파라메터인 'x' 값을 고정 시키겠다는 의미이다. 따라서 'bound(20)' 의 결과는 '30' 이 된다.


댓글 없음:

댓글 쓰기