[JS] 함수 (Function) - 추가 중

J.A.Y·2023년 8월 16일
0

javaScript

목록 보기
2/21

1. 함수 선언과 표현, 그리고 호이스팅

  • 함수 선언문(Declaration) : 함수 선언은 function으로 시작해서 함수 이름을 작성해줘야 한다. function 이름() {}

  • 함수 표현식(Expression) : const 또는 let으로 변수의 이름을 지정하고, 할당 연산자를 통해 function으로 시작한다. const 변수 = function ()

  • 함수 호출은 함수이름() 작성을 통해 이루어진다. 만약 함수이름만 작성하면 함수가 실행되는 것이 아니라 함수 데이터가 출력된다.

  • 함수 선언문과 함수 표현식은 호이스팅에서 분명한 차이점을 나타낸다.

🌟호이스팅이란? 함수가 선언되어져 있는 코드를 유효한 범위 안에서 가장 위로 끌어올리는 것이다. 이는 함수 선언문에선 적용되지만 함수 표현식에선 적용되지 않는다. 아래의 코드에서 함수 선언문의 위치가 더 아래 있으면서도 콘솔창에 hello가 정삭적으로 뜨는 이유는 호이스팅때문이다. 함수 선언문 대신 함수 표현식을 작성하면 에러가 발생한다.

hello()

function hello() {
	console.log('Hello~')
}

2. 반환 및 종료

  • retrun을 이용해서 데이터를 반환할 수 있고, 함수 호출을 통해 반환한 데이터를 불러올 수 있다.
function hello() {
	return 'Hello'
}

console.log (hello())   // Hello
  • 'return'은 함수 데이터를 함수 밖으로 내보내는 역할뿐만 아니라 함수의 동작을 멈추는 기능도 한다.
function hello() {
	return 'Hello'			// 동작 멈춤
    console.log('Bonjour') 	// 출력 안됨
}

console.log (hello())   // Hello

함수 응용ver.

// plus함수의 인수로 숫자를 받아 1을 더한다.
// num은 인수를 전달받는 매개변수이다.
// 숫자가 아닌 대상이 인수로 들어갔을 때 undefiend 또는 NaN 에러 발생하는 것 대신 안내문구와 0이 출력되도록 한다.
function plus(num) {
	if (typeof num !== 'number') {
    	console.log('숫자를 입력하십시오.')
    	return 0
    }
	return num + 1
}

console.log(plus(2));     //   3
console.log(plus());	  //   숫자를 입력하시오. 0

3. 매개변수 패턴(Parameter pattern)

  • 매개 변수와 동일하게 인수를 각각 적어 매개변수로 값을 전달할 수도 있고, 기호 =를 이용해서 매개변수의 기본값을 설정해줄 수도 있다.
  • 인수에 일부 값이 빠져 있을 경우 발생할 수 있는 undefined나 NaN 에러를 방지하기 위해 기본값을 설정해주곤 한다.
// a, b = 매개변수
// 1, 2 = 인수
function sum(a, b = 1) {
	return a + b
}

console.log(sum(1, 2))    //  3
console.log(sum(3))		  //  4

3-1. 매개변수와 구조 분해 할당 (Destructuring assignmnet):

  1. 객체 데이터 :
    (1) 함수 정의에 객체 데이터를 활용하는 방법
const user = {
	name: 'Apple',
    age: 110
}

function getName(user) {
	return user.name
    
}
console.log(getName(user))    // Apple
    (2-1) 함수 정의에 객체 데이터를 활용하는 방법 (구조 분해 할당)
const user = {
	name: 'Apple',
    age: 110
}

function getName(user) {
    // 'user'라는 객체 데이터의 구조를 분해해 name이라는 속성을 할당해준다.
    const {name} = user
	return name
}

console.log(getName(user))    // Apple
    (2-2) 함수 정의에 객체 데이터를 활용하는 방법
const user = {
	name: 'Apple',
    age: 110
}
// 객체 데이터의 구조를 매개 변수에 직접 분해 및 할당한다.
function getName({ name }) {
	return name
}

function getAge({ age }) {
	return age
}


console.log(getName(user))    // Apple
console.log(getAge(user))	  // 110
  1. 배열 데이터 :
    (1) 함수 정의에 배열 데이터를 활용하는 방법
const fruits = ['Apple', 'Banana', 'Pear']

function getFirstFruit(array) {
	return array[0]
}

conole.log(getFirstFruit(fruits))  // Apple
    (2) 함수 정의에 배열 데이터를 활용하는 방법 (구조 분해 할당)
const fruits = ['Apple', 'Banana', 'Pear']
const numbers = [1, 2, 3, 4, 5]

// fruits 배열의 구조를 직접 매개변수로 할당한다.
function getFirst([a]) {
	return a
}

function getSecond([, b]) {
	return b
}

conole.log(getFirst(fruits))  // Apple
console.log(getSecond(fruits)) // Banana

console.log(getFrist(numbers))  // 1
console.log(getSecond(numbers))  // 2 

3-2. 나머지 매개변수 (Rest parameter)

  1. 연산 함수

(예제1-1) 함수에 인수를 배열 데이터 타입으로 불러내는 방법

// 전개 연산자 + 매개 변수
// 전개 연산자를 사용하면 함수로 들어오는 모든 인수를 배열 데이터로 받아낸다.
function sum(...rest) {
	console.log(rest)    
}

function sum2(a, b, ...rest) {
	console.log(rest)    
}

console.log(sum(1, 2))  // 콘솔창에 배열 데이터로 뜬다.
console.log(sum(1, 2, 3, 4))  // 마찬가지
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))  // 마찬가지

// rest만 출력이므로 a와 b에 해당하는 1과 2만 출력되지 않는다.
console.log(sum2(1, 2)) //  []
console.log(sum2(1, 2, 3, 4))// (2)[3, 4]
console.log(sum2(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))// (8) [3, 4, 5, 6, 7, 8, 9, 10]

(예제1-2) 인수 합 구하기 ✨Reduce()✨

function sum(...rest) {
  // arguments: 배열 데이터와 유사한 데이터(=arraylike), 즉 완전히 같은 것이 아니므로 reduce와 같이 사용할 수 없다. 이는 item을 확인할 때 사용한다.
  	console.log(arguments)
  	return rest.reduce(function (acc, cur) {
    	return acc + cur	
    }, 0)
}

console.log(sum(1, 2))  // 3
console.log(sum(1, 2, 3, 4))  //  10
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))  // 55

4. 화살표 함수(Arrow function)

  • function대신 =>로 함수를 표현할 수 있다. 화살표 함수는 2015년에 새로 나온 문법이다.
// 화살표 기호 적용 전
function a () {}
const a = function () {}
const c = function (x, y) { return x * y}

//화살표 기호 적용 후
const a = () => {}
const b = x => {}  // 매개변수가 하나일 때는 소괄호 생략 가능
const c = (x, y) => x * y  // 함수 로직에 return이 가장 앞에 실행될 경우 return과 중괄호 생략 가능

const d = () => ({a: 1}) 
//객체 데이터의 중괄호와 함수의 중괄호 방식이 같아 중괄호만 적어주면 에러가 발생할 수 있다.
//에러를 방지하기 위해 이럴 때는 소괄호로 묶어준다.

const e = () => [1, 2, 3]
//배열 데이터는 객체 데이터와 달리 문법이 함수와 서로 겹치지 않기 때문에 그대로 적어주면 된다.

5. 즉시 실행함수(IIFE, Immediately-Invoked Function Expression)

//원래는 함수를 호출해야 실행할 수 있다.
const a = 7

const double = () => {
	console.log(a * 2)
}
double ()		// 14
// 함수를 별도로 호출하지 않아도 바로 실행 가능하다.
;(() => {
	console.log(a * 2)
})() 					//14
  • 이 외, 즉시 실행함수 문법들 :
// 가장 많이 사용되는 두 가지
;(() => {})()		    // (F)()
;(function () {})()		// (F)()

// 함수 키워드를 이용할 수 있는 다른 즉시실행함수 문법
;(function () {}())		// (F())
;!function () {}()		// !F()
;+function () {}()		// +F()

()() 즉시 실행 함수의 매개변수에 인수를 받는 법

;((a, b) => {
	a + b
})(1, 2)		// 3
  • 이 문법의 활용방법은 다양한데, 예를 들면 :
// 창의 가로 넓이와 doc의 body 요소를 사용한다.
;((a, b) => {
	console.log(a.innerWidth)	// 창의 가로넓이
  	console.log(b.body)    		// body 요소 
})(window, document)

6. 콜백 함수

💡from. 모던 자바스크립트 딥-다이브

  • 함수를 직접 호출하는 방식이 아니라 특정 이벤트가 발생했을 때 시스템에 의해 호출되는 함수이다.
  • 콜백 함수는 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수이다.
  • 콜백 함수는 매개변수를 통해 전달되고, 전달받은 함수의 내부에서 어느 특정시점에 실행된다.
  • 콜백 함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기 처리에 활용되는 중요한 패턴이다.

기본 문법 :

// 함수'a'를 실행했을 때 콘솔창에 'A'를 출력한다.
// 2-1. 매개변수 'callback'(다른 아무 이름도 가능)을 실행한다.
const a = callback => {
	console.log('A')
  	callback()
}

const b = () => {
	console.log('B')
}
// 2-2. 'callback'에 또 다른 함수 'b'를 할당한다.
a(b)	
		// A
		// B

💡from. 모던 자바스크립트 딥-다이브

  • 콜백 함수는 고차 함수에 전달되어 헬퍼 함수의 역할을 하기도 한다.
  • 콜백 함수의 장점으로는 함수 외부에서 고차 함수 내부로 주입하기 때문에 자유롭게 교체할 수 있다는 것이다. 이는 다시 말해, 콜백 함수는 고차함수의 일부분으로 합성되어 질 수 있다는 의미와 동일하다.

교재에 나와 있는 예제입니다.

function repeat(n, f) {
  for (let i = 0; i < n; i++) {
    f(i);
  }
};

var logAll = function(i) {
  console.log(i);
};

repeat(5, logAll);

var logOdds = function (i) {
	if (i % 2) console.log(i);
};

repeat(5, logOdds);

교재 외, 새로운 예제 : 콜백함수를 사용해서 html과 js 제어하기

//javascript
const loadImage = (url, callback) => {
	const imgEL = document.createElement('img')
  imgEL.src = url   // 1. html에서 함수 호출을 통해 url 정보를 받고
    imgEL.addEventLister('load', () => {  // 2. 받은 url을 통해 이미지가 로드 되고 콜백함수가 실행된다.
      setTimeout(() => {
       callback(imgEL) }, 1000)  // 3. 함수 내부의 또 다른 함수가 호출되면서 인수imgEL는 loadImage의 두 번째 인수에 매개변수로 전달이 가능해진다.
  })
}

//html
const containerEl = document.querySelector('.container')
loadImage(/* '링크주소' */, imgEL => {    // 4. 이미지 로드가 이미 끝난 imgEl를 매개변수로 전달받는다.
  containerEl.innerHTML = 'Loading...'   // 5. 전달받은 변수를 containnerEL에 활용한다.
  containerEl.append(imgEL)   // 6. append()메소드로 이미지를 밀어넣는다.
})

비동기 함수인 setTimeout함수는 콜백 함수의 대표적 예시이다.

  • setTimeout() 메서드 : 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머
var timeoutID = setTimeout(function[, delay]);

var timeoutID = setTimeout(function[, delay, arg1, arg2, ...]);
  • function: 타이머가 만료된 뒤 실행한 함수

  • delay : 주어진 함수를 실행하기 전에 기다릴 밀리초 단위 시간이다. 생략 또는 0을 지정할 경우 "즉시", 더 정확히는 다음 이벤트 사이클에 실행한다는 뜻이다.

  • arg1, ..., argN : function에 전달할 추가 매개변수

  • clearTimeout(): 타이머 취소

    • setTimeout()은 비동기 함수로서, 함수 스택의 다른 함수 호출을 막지 않는다. 따라서 setTimeout()를 여러 줄 만들고 각 줄들이 차례로 호출되도록 하려면 각 줄에 "정지" 구간을 만들어 줘야 한다.)
  • setInterval() : 어떤 함수를 몇 밀리초마다 반복적으로 호출

호출 방법 :
1. 비동기 함수를 다른 함수에 호출하기
2. 함수 내부에 직접적으로 비동기 함수를 정의하기

// return이 맨 앞일 경우 중괄호와 return을 생략할 수 있지만 이 경우엔 뒤에 나오므로 생략이 불가하다.
// a와 b의 인수로는 숫자
// c의 인수로는 함수addAB
// 함수sum 내부에는 1초 뒤에 함수c가 실행
// 코드c는 매개변수c가 받은 addAB함수가 호출되는 구조
// addAB함수가 호출 될 때, a와 b가 더한 값이 함수c의 인수로 들어감
// 함수c의 인수는sum함수가 호출 되면서 만들어지는 세 번째 인수에 해당하는 함수이므로, c의 인수는 addAB라는 매개변수로 할당되면서 콘솔창에 뜸

const sum = (a, b, c) => {
	setTimeout(() => {c(a+b)}, 1000)
}

sum(1, 2, addAB => {console.log(addAB)})		// 3
sum(3, 4, addAB => {console.log(addAB)})		// 7
  • Javascript가 비동기 언어임을 단적으로 보여주는 예시
function goMart() {
    console.log("마트에 가서 어떤 음료를 살지 고민한다.");
}
function pickDrink() {
    setTimeout(() => {
        console.log("고민 끝");
        product = "코카 콜라";
        price = 1000;
    }, 2000);
}
function pay(product, price) {
    console.log(`상품명: ${product}, 가격: ${price}`);
}

let product;
let price;
goMart(); //실행 순서: 1
pickDrink(); //실행 순서: 3
pay(product, price); //실행 순서: 2
  • 콜백 함수로 위의 예시를 동기적으로 처리할 수 있다.
function goMart() {
    console.log("마트에 가서 어떤 음료를 살지 고민한다.");
}
function pickDrink(cb) {
    setTimeout(() => {
        console.log("고민 끝");
        product = "코카 콜라";
        price = 1000;
        cb(product, price); // cb 추가, 콜백함수로 실행
    }, 2000);
}
function pay(product, price) {
    console.log(`상품명: ${product}, 가격: ${price}`);
}

let product;
let price;
goMart(); //실행 순서: 1  > 마트에 가서 어떤 음료를 살지 고민한다.
pickDrink(pay); // 실행 순서 2  > (2초 뒤) 고민 끝, 상품명: 코카 콜라, 가격: 1000

7. 재귀(Recursive) 함수

  • 자기 자신을 호출하는 것을 재귀 호출이라고 하는데, 재귀 호출을 동작하는 함수를 바로 재귀함수라고 한다.
  • 재귀 함수는 반복되는 처리를 위해 사용된다. 재귀 함수를 사용하면 반복문 없이도 구현할 수 있다.
  • 하지만 무한 반복에 빠질 위험이 있고, 이로 인해 스택 오버플로 에러를 발생시킬 수 있기 때문에 사용에 주의해야 한다.
  • 이러한 단점으로 인해 재귀 함수를 사용하는 편이 더 가독성이 좋아질 경우로 한정하여 사용하는 것이 일반적이다.
let i = 0;
const a = () => {
  console.log(1)
  i += 1;
  if (i < 3) {
 	a()			//재귀 호출
  }
}

a()	    // 1
		// 1
		// 1

8. 호출 스케줄링

  • 함수를 일정 시간이 지난 후 호출되도록 타이머를 거는 것을 호출 스케줄링이라고 한다.
  • 호출 스케줄링은 타이머 함수를 사용한다.
  • 타이머 함수는 ECMAScript의 빌트인 함수가 아니지만, 브라우저 환경과 Node.js환경에서 모두 전역 객체의 메서드로서 제공된다.
    즉, 타이머함수는 '호스트 객체'이다.

타이머 함수 :
1. setTimeout

const hello = () => {
	console.log ('Hello World!'}
                
setTimeout(hello, 1000)    // 1초 뒤 'Hello World!' 출력
  1. clearTimeout
//html
<h1>Hello World!<h1>

//javascript
const hello = () => {
	console.log ('Hello World!'}

const timeOut = setTimeout(hello, 5000)
const h1El = document.querySelector('h1')
h1El.addEventListener('click', () => {
  console.log('Time has cleared!')
  clearTimeout(timeOut)})
// html'h1' 글을 5초 전에 클릭하면 타이머 해제로 콜백 함수 실행X
// Hello World 대신 Time has cleared가 콘소창에 출력
  1. setInterval
const hello = () => {
	console.log ('Hello World!'}
                
setInterval(hello, 1000)   // 1초마다 반복해서 콜백 함수 실행
  1. clearInerval
//html
<h1>Hello World!<h1>

//javascript
const hello = () => {
	console.log ('Hello World!'}

const timeOut = setInerval(hello, 1000)
const h1El = document.querySelector('h1')
h1El.addEventListener('click', () => {
  console.log('Time has cleared!')
  clearInterval(timeOut)})
  • setTimeoutsetInerval는 모두 일정 시간이 경과된 이후 콜백 함수가 호출되도록 타이머를 생성한다.

  • setTimeoutsetInterval의 차이점 :
    - setTimeout : 타이머가 만료되면 콜백 함수를 딱 한 번 호출한다.
    - setInterval : 타이머가 만료될 매다마 콜백 함수를 반복 호출한다.


9. This

일반 함수의 this화살표 함수의 this
호출 위치에서의 정의자신이 선언된 함수(렉시컬) 범위에서 정의

9-1. 일반 함수의 this

9-2. 화살표 함수의 this

profile
Done is better than perfect🏃‍♀️

0개의 댓글