「웹해킹을 위한 자바스크립트(Javascript) 훑어보기」- 4. 함수

본 글은 Udemy(유데미)에서 제공하는 Colt Steele님의 「The Web Developer 부트캠프 2023」 강의를 수강하며 배운 내용을 바탕으로 작성했습니다. 

웹 해킹 및 보안에 쓰이는 자바스크립트 코드를 보고 이해할 수 있는 수준에 다다르기 위해 전반적인 내용을 가볍게 훑어보는 기획입니다.

 

함수

JS에서 함수의 기본적인 형태는 다음과 같습니다.

function add(x, y) 
{
	let sum = x + y;
	return sum;
}

 

어떤 프로그래밍 언어든 블록과 지역변수의 개념은 비슷합니다.

블록(중괄호 '{'와 '}' 사이) 안에 정의된 변수는 해당 블록 안에서만 사용할 수 있습니다.

 

그런데 let, const가 등장하기 전 사용했던 변수 선언 키워드인 var는 블록 범위의 영향을 받지 않습니다.

 

함수는 아니지만, 블록이 사용되는 for문을 예시로 살펴보겠습니다.

 

var 키워드로 선언한 변수는 for 범위 밖에서도 출력할 수 있습니다.

for(var i = 0; i < 5; i++) {
	var msg = "ASldksfjf"
	console.log(msg)
}
console.log(msg)
console.log(i)

/*
ASldksfjf
ASldksfjf
5
*/

 

let 키워드로 선언한 변수는 for 범위 밖에서는 사용할 수 없습니다.

for(let i = 0; i < 5; i++) {
	var msg = "ASldksfjf"
	console.log(msg)
}
console.log(msg)
console.log(i)

/*
ASldksfjf
ASldksfjf
Uncaught ReferenceError: i is not defined at <anonymous>:6:13
*/

렉시컬 스코프(lexical scope)

렉시컬 스코프는 중첩된 함수에서 내부(하위) 함수가 외부(상위) 함수의 정보에 접근할 수 있다는 개념입니다.

function outer() {
	const name = "Jack";
	function inner() {
		console.log(name);
	}
	inner();
}

함수 표현식(function expression)

함수를 조금 다른 방식으로 선언하는 방법입니다.

function 키워드 다음 함수 이름을 작성하는 대신, 변수에 값을 대입하듯이 함수를 선언합니다.

const add = function(x, y) {
	return x + y;
}

호이스팅(hoisting)

 

호이스팅(hoisting)이란 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다.

호이스팅 덕분에 함수를 정의하기 이전에 호출해도 에러가 발생하지 않습니다.

 

var로 선언한 변수는 호이스팅 시 undefined로 초기화되지만,

let과 const로 선언한 변수는 호이스팅 시 초기화되지 않습니다.

 

함수 표현식으로 함수를 정의하면 호이스팅이 일어나지 않습니다.

따라서 함수 표현식을 정의하기 전에는 사용할 수 없습니다.


고차 함수(Higher Order Function)

고차 함수는 함수를 인자로 전달받거나 함수를 결과로 반환하는 함수입니다.

 

다음 예제에서 callTwice() 함수는 함수를 인자로 받아 두 번 실행하는 고차 함수입니다.

function callTwice(func) {
	func();
	func();
}

function print() {
	console.log("Hello");
}

callTwice(print)

// result
/*
Hello
Hello
*/

 

makeRandomFunc()는 함수를 결과로 반환하는 고차 함수입니다.

function makeRandomFunc() {
	const rand = Math.random();
	if (rand > 0.3) {
		return function () {
			console.log("lucky");
		}
	}
}

 

도대체 왜 이런 형태의 함수를 사용하는 걸까요? 답은 추상화(abstraction)에 있습니다.

 

더 자세한 내용이 알고 싶으시다면 다음 블로그를 참고해 보세요.

https://velog.io/@thyoondev/고차-함수higher-order-function에-대하여


메서드(method)

지금까지 우리는 메서드라는 이름으로 계속 함수를 사용해 왔습니다.

메서드는 객체의 속성으로 추가되는 함수를 말합니다.

 

다음 예시에서 square와 cube는 myMath 객체의 선언된 함수 형태의 속성으로, 메서드입니다.

const myMath = {
	square: function (num) {
		return num * num;
	},
	cube: function(num) {
		return num ** 3;
	}
}

 

속성의 형태로 정의하지 않고 익숙한 형태로 정의할 수도 있습니다.

const myMath = {
	square(num) {
		return num * num;
	},
	cube(num) {
		return num ** 3;
	}
}

this

this는 호출한 객체 자기 자신을 가리키는 키워드입니다.

 

다음 코드에서 dog 객체의 메서드 bowWow()는 color 속성에 접근할 수 없습니다.

const dog = {
	name: "bark",
	color: "black",
	breed: "buul dog",
	bowWow() {
		console.log(color);
	}
}

//Uncaught ReferenceError: color is not defined 
//at Object.bowWow (<anonymous>:6:15)

 

this를 사용하여 호출 객체의 color 속성임을 명시해야 정상적으로 동작합니다.

const dog = {
	name: "bark",
	color: "black",
	breed: "buul dog",
	bowWow() {
		console.log(this.color);
	}
}

 

이번에는 bowWow() 메서드를 대입한 bowWow2라는 함수를 정의해 보겠습니다.

const bowWow2 = dog.bowWow;

 

이 함수를 실행하면 어떻게 될까요?

const dog = {
	name: "bark",
	color: "black",
	breed: "buul dog",
	bowWow() {
		console.log(this);
	}
}

dog.bowWow();  
//{name: 'bark', color: 'black', breed: 'buul dog', bowWow: ƒ
const bowWow2 = dog.bowWow;
bowWow2();
//Window {0: global, window: Window, self: Window, document: document, name: '', location: Location, …}

 

bowWow2는 dog 객체의 bowWow() 메서드를 가리키지만, 실행해 보면 Window라는 객체의 정보가 표시됩니다.

Window는 자동으로 만들어지는 최상위 객체입니다.

bowWow2 함수에서 'this'는 window 객체인 것입니다.