코딩 이것저것

[코딩] 자바스크립트 핵심 가이드(4)

홍써 2020. 5. 11. 20:50

이번 장은 함수에 대한 내용이다. 가장 중요하게 생각해도 되는 장이다. 함수형 자바스크립트에 대한 책도 많이 나와 있다. (추후에는 함수형 자바스크립트 입문 책도 샀으니 관련하여 정리할 예정이지만, 이 장은 자바스크립트 핵심 가이드에서 나온 내용을 주로 정리한다) 

함수는 모듈화의 근간, 코드의 재사용성, 정보의 구성 및 은닉 등에 사용, 객체의 행위를 지정하는데도 사용할 수 있음.  

함수 객체 

자바스크립트에서 함수는 객체임. 객체는 프로토타입 객체로 숨겨진 연결을 갖는 이름/값 쌍들을 집합체로 객체 중에서 객체 리터럴로 생성되는 객체는 Object.prototype에 연결됨. 반면 함수 객체는 Function.prototype에 연결됨(다시 Function은 Object.prototype에 연결됨) 

  • 모든 함수는 숨겨진 두 개의 추가적인 속성이 있음(함수의 문맥(Context)과 함수 행위를 구현하는 코드(code)임) 
  • 함수는 변수나 객체, 배열등에 저장, 다른 함수에 전달되는 인수로도 사용, 함수의 반환 값으로도 사용함 

함수 리터럴

  • 함수 객체는 함수 리터럴로 생성할 수 있음 
  • 함수 리터럴에는 네가지 부분이 있음 
    • 함수 리터럴로 생성한 함수 객체는 외부 문맥으로의 연결이 있음 → 클로저라고 함 

함수를 정의하는 방법(모던 자바스크립트 입문 책 참고) 

// 함수 선언문으로 정의하는 방법 

function square(x) { return x * x; } 

// 함수 리터럴로 정의하는 방법 
var square = function(x) { return x*x; } 

// Function 생성자로 정의하는 방법 
var square = new Function(“x”, “return x*x”; }  

// 화살표 함수 표현식으로 정의하는 방법 (ECMAScript 6부터 추가된 형태) 
var square = x => x*x; 

호출 

  • 함수를 호출하면 현재 함수의 실행을 잠시 중단하고 제어를 매개변수와 함께 호출한 함수로 넘김(콜백 지옥... 이 생기는 원리) 
  • 모든 함수는 명시되어 있는 매개 변수에 더해서 this라는 매개변수는 객체 지향 프로그래밍 관점에서 매우 중요함(함수형 프로그래밍인 동시에 객체 지향형 프로그래밍임) 
  • 매개변수는 호출하는 패턴에 의해 결정됨 
    • 메소드 호출 패턴: 함수를 객체의 속성에 저장하는 경우 
    • 함수 호출 패턴: 함수가 객체의 속성이 아닌 경우에는 함수로 호출 
    • 생성자 호출 패턴: 프로토타입에 의해서 상속이 이루어지는 언어로, 객체가 자신의 속성들을 다른 객체에 바로 상속할 수 있다는 뜻 → new로 생성하면 this에 바로 바인딩됨 
    •  apply 호출 패턴: apply 메서드는 함수를 호출할 때 사용할 인수들의 배열을 받아들여서 this값을 선택할 수 있도록 해줌. 

인수 배열(arguments) 

추가적인 매개변수로 arguments라는 배열을 사용할 수 있음. 이 배열은 함수를 호출할 때 전달된 모든 인수를 접근할 수 있게 함(하지만 유용한 패턴은 아니라고 하니 조심하자) 

var sum = function( ) { 
	var i , sum. = 0 ; 
    for(i = 0 ; i < arguments.length; i+=1) {
    	sum += arugments[i]; 
     } 
     return sum; 
} 

document.writeln(sum(4,8,15,16,23,42)); // 108 

반환(return) 

  • return 문은 함수가 끝에 도달하기 전에 제어를 반환할 수 있음 
  • 반환값이 지정되지 않으면 undefined가 반환됨 

예외 

  • 예외는 정상적인 프로그램의 흐름을 방해하는 비정상적인 사고임 
  • 예외 객체는 try문의 catch절에 전달됨 
var try_it = function( ) { 
	try {
    	add("seven"); 
    } catch(e) { 
    	// add를 잘못 호출하면 여기로 들어오므로 여기서 처리하자 
    	document.writeln(e.name + ": " + e.message); 
    }
} 

try_it() ;

 

기본 타입에 기능 추가 

언어의 기본 타입에 기능을 추가할 수 있음(강력한 기능이다) 

예를 들어 다음과 같이  method라는 메소드를 Function.prototype에 추가하면서 이후 모든 함수에서 이 메서드를 사용할 수 있음 

Function.prototype.method = function(name, func) {
	this.prototype[name] = func; 
    return this; 
}; 

 자바스크립트에는 문자열의 양 끝에 있는 빈칸을 지우는 메소드가 없는 경우에도 다음과 같이 정의해서 사용하면 된다고(오호 +ㅂ+) 

String.method('trim', function(){
	return this.replace(/^\s+|\s+$/g, ''); 
}); 

document.writeln('"' + " 	neat	".trim() +'"'); 

재귀적 호출 

유효범위(Scope) 

ECMAScript 6부터 let을 사용하여 지역으로 유효 범위를 제한할 수 있다 { let xx } 범위임 

for(let i =0 ; i < elm.length ;i++){ 
//let 유효 범위임 
	elm[i].onclick = function(){
    	console.log(i); 
    } 
// end of let scope
} 

클로저(Closure) 

  •  내부 함수에서 자신을 포함하고 있는 외부 함수의 매개변수와 변수들을 접근할 수 있다 
  •  

<변수에 접근하지 못하는 예> 

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

<get_status메서드가 있는 객체를 반환 -> 객체에 대한 참조를 myQuo에 저장 -> 이미 반환된 뒤에도 quo의 status에 접근할 수 있음 >

var quo = function(status){
	return {
    	get_status : function(){
        	return status ; 
        } 
    }; 
}; 

var myQuo = quo("amazed");  // myQuo에 저장함 

document.writeln(myQuo.get_status()); // myQuo를 통하여 status를 접근할 수 있음 

(추가적으로 업데이트 하겠다. 오늘은 여기까지만) 

콜백(Callback) 

  • 비연속적인 이벤트를 다루는 것에 대해서 쉽게 할 수 있는 방법을 제공 
  • 비동기식 함수로 정의하여 구현함 
request = prepare_the_request(); 

// furesponse를 받는 함수를 정의하여 response가 왔을 때 실행할 수 있도록 구현함 
send_request_asynchronously(request, function(response){ 
	display(response); 
}); 

 

커링(Curry) 

  • 커링이란 인수를 두 개 이상 받는 함수를 분해하여 인수가 하나인 함수의 중첩 함수로 변환하는 작업을 말함 
  • 장점: 부분 적용한 함수를 쉽게 만들어낼 수 있음 
var pow = function(exponent){ 
	return function(base){ 
    	return Math.pow(base, exponent); 
    }; 
}; 

pow -> Math.pow를 커링한 것임 
Math.pow(base, exponent) = pow(exponent)(base) 

var square = pow(2); 
var sqrt = pow(.5) ; 
var cubicroot = pow(1/3); 

고차 함수와 커링 함수를 조합  

var sum = function(a,b){return a+b; }; 
var a = [1,2,3,4]; 
var abs_a = pow(.5)(a.map(pow(2)).reduce(sum));