본문 바로가기

Javascript/Javascript(2022 version)

Javascript 기초(7) - 함수, 콜스택, 스코프 체인, this

728x90
반응형

1) Javascript 복습

   1-1) 함수 선언과 호출

   1-2) 콜스택

   1-3) 스코프 체인

   1-4) this

   1-5) function(this binding)

   1-6) function의 다양한 활용

 

 

 

 

 

1) Javascript 복습

1-1) 함수 선언과 호출

함수 선언과 호출의 차이를 이해하는 것이 중요하다!!

함수 선언문

function add(a, b) {
	return a + b;
}

add(1, 2); // 결과: 3

function calculator(func, a, b) {
	return func(a, b);
}

calculator(add, 1, 2); // 결과: 3


함수 표현식(arrow function)

const add = (a, b) => a + b;
const calculator = (func, a, b) => func(a, b);

calculator(add, 1, 2);

// 가장 많이 헷갈리는 부분이 함수 선언과 호출을 정확히 인지하지 못한다는 점이다!!

const add = (a, b) => a + b;
document.querySelector('#header').addEventListener('click', add());
// header에 대한 이벤트가 안 먹히는 이유 : 함수를 이미 호출했기에 호출할 함수가 없어 위의 코드는 동작하지 않음!!


응용문제
함수 선언문

function clickHandler() {
	console.log('hello world!');
}

document.querySelector('#header').addEventListener('click', clickHandler());
// header에 대한 이벤트가 안 먹히는 이유 : 위의 경우도 마찬가지로 함수를 이미 호출했기에 호출할 함수가 없어 해당 코드는 동작하지 않음!!

function clickHandler() {
	return function() {
		console.log('hello world!');
	}
}

document.querySelector('#header').addEventListener('click', clickHandler());
// 고차함수를 사용하면 이 경우에는 이벤트가 정상적으로 동작함!!


함수 표현식(arrow function)

// 고차함수 사용 case
const clickHandler = () => () => console.log('hello world!');
document.querySelector('#header').addEventListener('click', clickHandler());



 

1-2) 콜스택

function c() {
	console.log('c');
}

function a() {
	console.log('a');
	function b() {
		console.log('b');
		c();
	}
	b();
}

a();
c();

/*
	출력 결과
	a
	b
	c
	c
*/

 

 

 

1-3) 스코프 체인

const x = 'x';
function c() {
	const y = 'y';
	console.log('c', x);
}

function a() {
	const x = 'xx';
	console.log('a', x);
	function b() {
		const z = 'z';
		console.log('b', x);
		c();
	}
	b();
}

a();
c();

/*
	출력 결과
	a xx
	b xx
	c x
	c x
*/

 

※ 렉시컬 스코프

 

 

 

1-4) this

"this"는 함수가 실행될 때 결정됨!
function 때문에 "this"를 이해하기 어려운데 이는 function이 하는 역할이 너무 많기 때문이다!!

함수를 사용하는 사례

  • 일반함수로 사용하는 경우
  • 생성자 함수로 사용하는 경우
  • 객체 메서드로 할당하는 경우

(1) 일반함수로 사용하는 경우

function Foo(a, b) {
	console.log(this); // window(전역객체)
	return [a, b];
}

const foo = Foo(1, 2);
console.log(foo); // [1, 2]


(2) 생성자 함수로 사용하는 경우

function Foo(a, b) {
	// this = {};
	console.log(this); // Foo {}
	this.arr = [a, b];
	// return this;
}

const foo = new Foo(1, 2);
console.log(foo); // Foo { arr: [1, 2] }

// this 바인딩이 일어남
// function에다가 this를 새로 할당해주기에 처음 this를 찍어보면 빈 객체로 찍힘!!
// 이를 '동적 바인딩'이라고 함


(3) 객체 메서드로 할당하는 경우

function Foo(a, b) {
	console.log(this); // bar
	return [a, b];
}

const bar = {
	method:Foo;
}

bar.method(1, 2); // [1, 2]

 

 

 

1-5) function(this binding)

간단한 일반함수
일반함수는 선언 시 생성자 함수가 존재한다!!

function a() {};
console.dir(a);


arrow function은 일반 함수로만 사용하라고 해서 ES6에서 새로 만든 것이다!!
arrow function은 생성자 함수가 없다!!

const b = () => {};
console.dir(b);


function.prototype.bind

function Foo(a, b) {
	console.log(this); // window(전역객체)
	return [a, b];
}

// 1: this에 넣을 값
// return: 함수값을 리턴
const fooBind = Foo.bind({name:'sangbeom'});
fooBind();
/*
	출력 결과
	{name: 'sangbeom'}
	[undefined, undefined]
*/

fooBind(1, 2);
/*
	출력 결과
	{name: 'sangbeom'}
	[1, 2]
*/

const bar = {
	method:fooBind;
}

bar.method(5, 6);
/*
	출력 결과
	{name: 'sangbeom'}
	[5, 6]
*/


공통점 : 함수에다가 this 값을 넣겠다는 목적을 가지고 있다!!

  • bind 함수 : return 값으로 함수를 다시 반환해줌!
  • call 함수 : call 함수를 실행하는 순간, this를 넣고 실행시켜 버림!
  • apply 함수 : call 함수와 마찬가지로 함수를 실행시켜 주지만 인수를 넣을 때 차이점이 있음!
function Foo(a, b) {
	console.log(this); // window(전역객체)
	return [a, b];
}

Foo.call({name: 'sangbeom'}, 1, 2);
/*
	출력 결과
	{name: 'sangbeom'}
	[1, 2]
*/

// apply 함수는 두번째 인수가 무조건 배열이다!!
Foo.apply({name: 'sangbeom'}, [1, 2]); // 인수, 매개변수
/*
	출력 결과
	{name: 'sangbeom'}
	[1, 2]
*/

 

 

 

1-6) function의 다양한 활용

function 키워드는 최대한 자제하는 것이 좋다!
일반함수(function 키워드) 안에 있는 this는 무조건 window 객체를 말함!!

function a() {
	console.log(this);
	function b() {
		console.log(this);
		function c() {
			console.log(this);
		}
		c(); // window(전역객체)
	}
	b(); // window(전역객체)
}
a(); // window(전역객체)

 

  • 일반함수를 쓸 때는 "arrow function"을 써야 함!
  • 생성자 함수를 쓸 때는 "class"를 써야 함!
  • 객체 메서드 할당 시에는 "메서드 축약형"을 써야 함!

 

일반함수는 arrow function으로 대체할 것!

 

arrow function

  • arrow function은 생성자 함수가 안 됨!!
  • arrow function은 bind가 안 됨(애초에 bind가 안 되도록 설계됨!)