[자바스크립트] 함수 호출 4가지 패턴 자유.플밍

자바스크립트의 함수 호출 패턴을 정리합니다. 
(발췌 : 자바스크립트 핵심 가이드, Douglas Crockford 저)

책이 2008년에 인쇄되었는데 자바스크립트의 변경된 스펙까지는 반영하지 못하였습니다.
단순히 책의 설명을 발췌하고 당시 자바스크립트의 설계를 이해하는데 초점을 맞춥니다.


1. 메소드 호출 패턴
함수를 객체의 속성에 저장하는 경우, 이 함수를 메소드라고 부릅니다. 
이 메소드를 호출할 때 this는 메소드를 포함하는 객체에 바인딩됩니다. (이 경우 this는 객체 자체)
var myObject = {
value: 0,
increment: function(inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};

myObject.increment();
document.writeln(myObject.value); // 1

myObject.increment(2);
document.writeln(myObject.value); // 3

2. 함수 호출 패턴
함수가 객체의 속성이 아닌 경우에는 함수로서 호출합니다.
var sum = add(3, 4); // sum is 7
이 경우 this는 전역객체에 바인딩됩니다.
이런 특성은 언어 설계 단계에서의 실수입니다. 만약 언어를 바르게 설계했다면, 내부 함수를 호출할 때 이 함수의 this는 외부 함수의 this 변수에 바인딩 되어야 합니다. 이러한 오류의 결과는 메소드가 내부 함수를 사용하여 자신의 작업을 돕지 못한다는 것입니다. 왜냐하면, 내부 함수는 메소드가 객체 접근을 위해 사용하는 this에 자신의 this를 바인딩하지 않고 엉뚱하나 값(전역객체)에 연결하기 때문입니다.

이러한 문제를 해결하기 위한 대안으로, 다음의 방법이 있습니다.
메소드에서 변수를 정의한 후 여기에 this를 할당하고, 내부 함수는 이 변수를 통해서 메소드의 this에 접근하는 방법입니다. 관례상 이 변수의 이름을 that이라고 하여 다음과 같이 구현할 수 있습니다.
var add = function (a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw {
name: 'TypeError',
message: 'add needs numbers'
}
}
return a + b;
}

var myObject = function ( ) {
var value = 0;

return {
increment: function (inc) {
value += typeof inc === 'number' ? inc : 1;
},
getValue: function ( ) {
return value;
},
setValue: function ( v ) {
value = v;
}
}
}( );

myObject.double = function ( ) {
var that = this; // Workaround.

var helper = function ( ) {
that.setValue(add(that.getValue(), that.getValue()));
};
helper( ); // Invoke helper as a function.
};

myObject.increment( ); // 1
myObject.increment(2); // 3
myObject.double( );
console.log(myObject.getValue( )); // 6
nodejs로 테스트 하였습니다. 책에 기제된 테스트 코드가 동작하지 않아 약간의 수정을 하였습니다.


3. 생성자 호출 패턴
자바스크립트는 프로토타입에 의해서 상속이 이루어지는 언어입니다. 이 말은 객체가 자신의 속성들을 다른 객체에 바로 상속할 수 있다는 뜻입니다. 자바스크립트는 클래스가 없습니다.
이러한 특성은 현존하는 언어들의 경향과는 다른 급진적인 것입니다. 프로토타입에 의한 상속은 매우 표현적이지만 널리 알려져 있지 않습니다. 자바스크립트 자체도 자신의 프로토타입적 본성에 확신이 없었던지, 클래스 기반의 언어들을 생각나게 하는 객체 생성 문법을 제공합니다.

함수를 new라는 전치 연상자와 함께 호출하면, 호출한 함수의 prototype 속성에 연결되는 (숨겨진) 링크를 갖는 객체가 생성되고, 이 새로운 객체는 this에 바인딩 됩니다.
// Create a constructor function called Quo.
// It makes an object with a status property.
var Quo = function (string) {
this.status = string;
};

// Give all instances of Quo a public method
// called get_status.
Quo.prototype.get_status = function ( ) {
return this.status;
};

// Make an instance of Quo.
var myQuo = new Quo("confused");
console.log(myQuo.get_status( ));

4. apply 호출 패턴
자바스크립트는 함수형 객체지향 언어이기 때문에, 함수는 메소드를 가질 수 있습니다.
apply 메소드는 함수를 호출할 때 사용할 인수들의 배열을 받아들입니다. 또한 이 메소드는 this의 값을 선택할 수 있도록 해줍니다. apply 메소드에는 매개변수 두개가 있습니다. 첫 번째는 this에 묶이게 될 값이고, 두 번째는 매개변수들의 배열입니다.
var add = function (a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw {
name: 'TypeError',
message: 'add needs numbers'
}
}
return a + b;
}

var Quo = function (string) {
this.status = string;
};

Quo.prototype.get_status = function ( ) {
return this.status;
};

// Make an array of 2 numbers and add them.
var array = [3, 4];
var sum = add.apply(null, array); // sum is 7

// Make an object with a status member.
var statusObject = {
status: 'A-OK'
};

// statusObject does not inherit from Quo.prototype,
// but we can invoke the get_status method on
// statusObject even though statusObject does not have
// a get_status method.
var status = Quo.prototype.get_status.apply(statusObject);
console.log(status); // status is 'A-OK'
apply : 첫번째 인자의 객체에 두번째 인자의 배열을 파라미터로 넘긴다.
call : 첫번째 인자의 객체에 두번째부터의 인자를 파라미터로 넘긴다.





덧글

댓글 입력 영역