Javascript

[Javascript] ES6 / 익명함수 / 가변인자 함수 / 콜백함수 / 클로저 함수

sian han 2022. 6. 22. 14:19

자바 스크립트의 기본 자료형

 : 숫자, 문자열, 논리형, 객체, 함수, undefined

 

  Q. 함수가 자료형 ? 🔽 이런형태

  - 함수를 변수에 넣을수도 있고 매개변수가 될 수도있고 반환타입이 될 수도 있음

함수 표현식
var add = function(a, b) {
return a + b;
};
var result = add(10, 20);

//var name='홍길동'; //변수에 문자열 데이터 넣기
function hello(name){
	document.write(name+"님 환영합니다.<br>");
}
hello('김길동');
var test=hello; //변수에 함수 넣기
test('이길동');

 

 

 

 

 

 

▶ 익명함수

 

• 함수를 선언하는 방법

 

1) 함수 표현식

     - 함수이지만 이름이 없으므로 익명함수라고 부름

     - 이름이 없으므로 변수에 넣어서 사용

var 함수 = function() { ... }
var str = function () {
    	var output = prompt('숫자를 입력해주세요.', '숫자');
    alert(output);
    };
str();
var sumNumbers = function(a, b) {
	return a + b;
};
var result=sumNumbers(10,20);
alert(result); //30

 

 

 

2) 함수 선언문

     - 이름이 있는 함수

function 함수() { ... }
function sumNumbers(a, b) {
	return a + b;
}

 

 

 

 

 

 

 

▶ 가변인자 함수

 

     - 매개변수의 개수가 변할 수 있는 함수

     - 자바스크립트는 매개변수의 개수를 정의된 것과 다르게 사용해도 되지만,

        가변인자 함수는 매개변수를 선언된 형태와 다르게 사용했 을 때, 매개변수를 모두 활용하는 함수를 의미함

 

▷ arguments

자바스크립트의 모든 함수는 내부에 변수 arguments 가 기본적으로 있다

     - arguments - 매개변수의 배열

     - arguments 객체의 자료형과 배열의 길이 출력하기

 

ex )   매개변수로 입력된 숫자를 모두 더하는 sumAll() 함수 작성

// 함수를 생성합니다.
function sumAll() {
// 출력합니다.
    alert(typeof (arguments) + ' : ' + arguments.length);
}
// 함수를 호출합니다.
sumAll(1, 2, 3, 4, 5, 6, 7, 8, 9);

 

 

 

 

콜백함수

  - 매개변수에 오는 함수를 콜백함수라함

  - 자바스크립트에서는 함수도 하나의 자료형이므로 매개변수로 전달할 수 있음

  - 주로 이벤트 리스너로 사용된다

 

ex )  callTenTimes() - 함수를 매개변수로 받아 해당 함수를 10번 호출하는 함수

// 함수 선언
function callTenTimes(callback) {
// 10회 반복
        for (var i = 0; i < 10; i++) {
        // 매개 변수로 전달된 함수를 호출
        callback();
        }
     }
// 변수를 선언
var callback = function () {
	alert('함수 호출');
};
// 함수를 호출
callTenTimes(callback);

 

 

 

이벤트리스너

$("#btnStart").click(function () {
	alert("클릭되었습니다.");
});

 

 

 함수를 리턴하는 함수함수를 리턴하는 함수

// 함수를 생성합니다.
function testFunction() {
    return function () {
   		alert('Hello Function .. !');
    };
}
// 함수를 호출합니다.
//testFunction()(); //함수를 호출하면 함수가 리턴되므로 괄호를 한 번 더 사용해 해당 함수를 호출
var result = testFunction();
result();

  - 함수를 리턴하는 함수를 사용하는 가장 큰 이유는 클로저 때문

 

 

 

클로저 함수

Q. 클로저 ?

  => 함수 내부에 만든 지역변수가 사라지지 않고 계속해서 값을 유지하고 있는 상태를 말함 (일종의 현상이다)

 

변수가 메모리에서 제거되지 않고 계속해서 값을 유지하는 상태를 클로저라고 부르며

내부에 있는 함수를 클로저함수라고 함

 

 

 일반 함수인 경우

/ 예제01: 일반 함수인 경우
function addCount(){
    var count=0;
    count++;
    return count;
}
document.write("1. count = "+addCount(),"<br>"); //count = 1
document.write("2. count = "+addCount(),"<br>"); //count = 1
document.write("3. count = "+addCount(),"<br>"); //count = 1

 

 

 클로저를 사용한 경우

function createCounter(){
    var count=0;
    function addCount(){
        count++;
        return count;
	}
return addCount;
}
var counter = createCounter(); (1)
document.write("1. count = " + counter(),"<br>"); // count = 1
document.write("2. count = " + counter(),"<br>"); // count = 2
document.write("3. count = " + counter(),"<br>"); // count = 3

(1) createCounter() 함수가 호출되면 지역변수 count가 0으로 초기화됨과 동시에 만들어 짐.

       그리고 내부에 addCount() 함수도 만들 어지고, 마지막으로 addCount() 함수를 리턴하고

        createCounter()함수는 종료됨

(2) 에서 counter()가 실행되면 addCount()함수가 실행되어

       증가 연산자에 의해서 count값 이 0에서 1로 증가하기 때문에 1이 출력됨

(3) ,(4) 둘 모두 counter()가 실행되면 count값 이 증가하기 때문에 2와 3이 출력됨

 

createCounter()가 종료되면 일반함수처럼 addCount()함수와 count 는 사라질까?

  - createCounter()가 종료되더라도 사라지지 않 고 계속해서 값을 유지하고 있게 됨

  - 이유는 addCount() 함수 내부에 count변수를 사용하고 있는 상태에서 외부로 리턴되어 클로 저 현상이 발생하기 때문

 

 

 

ex )   버튼을 클릭하면 클릭할 때마다 1씩 증가시켜 주세요.

<script>
// 예제 03: 버튼을 클릭하면 클릭할 때마다 1씩 증가시켜 주세요.
window.onload=function() {
document.getElementById("btnStart").onclick = function () {
start();
document.write("시작합니다.");
};
function start() {
var count = 0;
setInterval(function () {
count++;
document.write(count);
}, 1000);
}
};
</script>
</head>
<body>
<button id="btnStart" >시작</button>
</body>

 

 

 

 


 

 

※ ES6

 

Q. ECMAScript ? 

  = > ECMAScript (또는 ES) : 자바스크립트 표준 문법

 

     - ES6 : ECMAScript 표준의 6 버전

     - 기존에 배운것들은 모두 ES5 였고, ES6 으로 넘어오면서 많은 변화가있었음

     - 현재의 자바스크립트는 ECMAScript와 BOM(Browser Object Model)와

        DOM(Document Object Model)을 포괄하는 개념이다.

 

 

 

▶ const, let

  - ES6 이전에 변수를 선언하는 방법은 var 

  -  let, const 는 기본적으로 var과 다르게 재선언이 불가능

  -  const : 재할당도 불가능 ( = java Final (상수) 과 흡사 ) : 배열이나 속성 객체는 추가 가능

     let : 재할당 가능 ( = java 변수와 흡사 )

 

 

▷ var

  - var의 유효 범위는 함수의 블록 단위로 제한됨

var a = 100;
function print() {
    var a = 10;
    console.log(a); //10
}
print(); // 10

 

 

const & let

  - 자바와 흡사해짐

  - const와 let의 변수 유효 범위를 블록{}으로 제한

var a = 10;
for (var a = 0; a < 5; a++) {
	console.log(a); // 0 1 2 3 4
}
console.log(a); // 5
var a = 10;
for (let a = 0; a < 5; a++) {
	console.log(a); // 0 1 2 3 4 
}
console.log(a); // 10

  = > 반복문의 조건 변수 a를 let으로 선언하면 변수의 유효 범위가 for 반복문의 {} 블록 안으로 제한됨

 

 

 

 

 

▶ 화살표 함수

  - ES6에 추가된 문법

 

 

기존 함수

function func(){
    const data = 'hello wolrd';
    return data;
}

🔽

함수 표현식

const func = function(){
    const data = 'hello wolrd';
    return data;
}

 

 

🔽

 

화살표 함수

const func1 = () =>{
    const data = 'hello wolrd';
    return data;
}

🔽

매개변수가 1개 라면 괄호 생략 가능

const func2 = num =>{
    return num;
}

🔽

🌟바디가 1개라면 중괄호와 return 생략 가능🌟

const func3 = num => num + 1;

 

 

단순한 자바스크립트 표현식

() => 10 + 20; // {} 필요 없음

 

() => {
    print();
    log();
    return 10 + 20;
};

 

 

 

 

 

 

▶ 배열관련 메소드

 

[1] map

   - 리액트를 하면서 가장 많이 사용하는 메소드 중 하나

   - 배열.map

   - 배열관련메서드들은 모두 콜백함수가 들어감 ( = 매개변수가 함수 )

   - map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후

     그 결과로 새로운 배열을 생성함

 

const list = [1, 2, 3, 4, 5].map((currenValue, index, array) => { 
	return currenValue + 1;
});

//결과 [2, 3, 4, 5, 6]

 

 = > 배열.map 은 배열을 리턴한다

 

🔽 바디가 하나이니까 중괄호와 return 생략 

const list = [1, 2, 3, 4, 5].map((currenValue, index, array) => 
currenValue + 1 );

 

 

 

 

[2] filter

   - 기존 ES5에서 배열에서 값을 제거하려면 indexOf 와 split 등 복잡한 과정을 거쳤지만,

      filter를 사용한다면 쉽게 제거할 수 있다. 

           ㄴ 원하는것만 추출하니까 필요없는건 제거되는거임

   - 조건이 참이라면 요소를 반환하고 거짓이라면 반환하지 않는다.

const list = [1, 2, 3, 4, 5].filter((currenValue, index, array) => 
currenValue % 2 === 0 )
//list : [2, 4]

 

 

ex )  문자의 길이가 5보다 큰 과일들만 배열에 담는 예제

출처 : https://brunch.co.kr/@swimjiy/15

const fruits =['APPLE','BANANA','LEMON','WATERMELON'];
const fuitsFilter = fruits.filter(word => word.length > 5);

console.log(fruitsFilter);
//['BANANA','WATERMELON']

 

 

❗️ map과 filter의 공통점은 기존배열은 건드리지 않으면서 요소들을 순회한 후 새로운 배열을 리턴한다는 것이고, 

차이점은 map은 콜백함수가 적용된 새 요소, filter는 조건문을 만족한 요소들을 반환한다는 점입니다.

출처 : https://velog.io/@tjdud0123/javascript-map-filter-%ED%95%A8%EC%88%98

 

 

 

 

 

[3] reduce

값을 누적시킬때 유용

함수 다음에 들어가는 초기값이 중요한데 처음 루프가 돌때 아래 코드에 들어간 0 이 previousValue로 들어가게된다.

const total = [1, 2, 3, 4, 5].reduce((previousValue, currentValue, 
currentIndex, array) => {
return previousValue += currentValue
}, 0);

  = > 초기값 : 0

previousValue 의 초기값은 0이고

배열 1,2,~ 를 currentValue 에 계속 더해나가는(= 누적) 것이다

 

 

const numbers = [1, 2, 3, 4, 5]
const summary = numbers.reduce((accumulation, currentValue, currentIndex, array) => { 
    console.log(accumulation, currentValue, currentIndex, array);
    return accumulation + currentValue;
}, 0);
console.log(summary);

accumulation 의 초기값은 0이고,

accumulation + currentvalue 한 값이 다시 accumulation 이 된다

 

 

 

 

spread

  - 배열을 분해하거나 객체를 분해하여 각각의 요소로 만든다.

 

let list = [1, 2, 3];
console.log(list); // [1, 2, 3]
console.log(...list); // 1, 2, 3

배열에서 각각의 요소만 가져와서 1,2,3  => 각각의 '값' 을 가져온다

 

 

 

▷ 배열복제 + 배열추가

let me = { name : 'hong', age : 21 } ;
me = {...me, married : false} // { name : 'hong', age : 21, married : false }

 

▷ 배열복제

  - '...' 사용

const array = [1,2,3,4,5];
const newArray = [...array];

 

▷ 배열복제 + 배열에 요소 추가 + 값 변경

  - pd 변수에 product의 요소를 넣고

  - desc 요소를 추가하고 price 값을 1,000,000으로 변경

const product ={
			pdName :'컴퓨터',
			price : 1500000,
			company : 'dell'
	};
var pd = {...product, price:1000000,desc:'어쩌구'};
console.log(pd);
  1. company: "dell"
  2. desc: "어쩌구"
  3. pdName: "컴퓨터"
  4. price: 1000000

 

// obj 객체를 newObj 객체에 복제
var obj = {
    a: 10,
    b: 20
};
var newObj = {...obj};
console.log(newObj); // {a: 10, b: 20}

// arr 배열을 newArr 배열에 복제
var arr = [1,2,3];
var newArr = [...arr];
console.log(newArr); // [1, 2, 3]
 => 중괄호를 쓰면 객체가된다. 
    얘는 key value 쌍이 아니니까 배열 대괄호[] 를 사용해야함

 

 

 

 

 

 

 

 

 

 

 destructuring

  - 배열과 객체의 값을 쉽게 추출 할 수 있다.

배열구조 : []

객체구조 : {}

 

구조 : 왼쪽에 변수가 오고 오른쪽에 데이터가 오는 형식

destructuring : 변수선언형식이 자유로워짐

 

var obj = {
	a: 10, b: 20, c: 30
};

var { a, b, c } = obj;

console.log(a); // 10 console.log(b); // 20 console.log(c); // 30

 => 객체 a,b,c 에 obj 의 키값이 들어감

 

 

 

 

▷ 특정 객체의 값을 꺼내오는 방법

 

 - 기존

var person = {
    name: 'hong',
    address: 'seoul',
    hobby: 'sports',
    age: '20'
};

var name = person.name;
var address = person.address;
var hobby = person.hobby;
var age = person.age;

 

 

 - 구조 분해 문법(Destructuring)

var { name, address, hobby, age } = person;

console.log(name); // hong
console.log(address); // seoul
console.log(hobby); // sports
console.log(age); // 20

 

 

 

 

 

 

 

 

 

 향상된 객체 리터럴(Enhanced Object Literal)

   - 자주 사용하던 문법들을 좀 더 간결하게 사용할 수 있도록 객체 정의 형식을 바꿨다

 

기존 객체 정의 방식

 - 속성 : 값

 - key : value

var person = {
    // 속성: 값
    address: 'seoul',
    coding: function() {
   	 console.log('Hello js');
    }
};

 

▷ 축약문법

  - 속성과 값이 같으면 1개만 기입

  - style 같은곳에 많이 씀

var address = 'seoul';
    var person = {
    	//address : address,
   	 address
    };
console.log(person); // {address: "seoul"}
// #2 - 라우터 등록 방식에서의 축약 문법
const router = new VueRouter({
    // ...
});

new Vue({
    // router: router,
    router
});

 

 

▷ 축약문법2

  - 속성에 함수를 정의할 때 function 예약어 생략

 

기존

const person = {
    // 속성: 함수
    coding: function() {
    	console.log('Hello js');
    }
};
person.coding(); // Hello js

 

 

ES6

const person = {
    coding() {
    	console.log('Hello js');
    }
};
person.coding(); // Hello js

  = > function 예약어를 생략해도 동일하게 동작

 

 

 

기존 this 바인딩

var person = {
    name: 'Kim',
    introduce: function () {
        console.log(this.name);
    }
};       

person.introduce(); // this는 메소드를 호출한 객체인 person를 가리킨다.
이 코드를 실행하면 Kim 이 콘솔에 출력됩니다.

 

 

ES6

  - ES6에서 메소드를 만들 때 this를 정적으로 객체에 바인딩하고 싶다면 축약 메소드를 사용해야 합니다.

출처 : https://cocoder16.tistory.com/49

const person = {
    name: 'Kim',
    introduce () {
        console.log(this.name);
    }
};
        
person.introduce(); // this는 정적으로 person 객체에 바인딩 됩니다.

 

 

 

실습

const person = {
		   name:'홍길동',
		   age:20,
		   job:'programmer'
		};

		//[1] p 변수에 person객체의 요소를 넣고, age 값을 25으로 변경하고
		//address 추가 
		
		const p = {...person, age:25, address :'신촌동'	};
		console.log(p);

		const arr=[7,8,9,10];

		//[2] 4개의 변수에 arr 요소의 값 넣기 
		var {a,b,c,d} = arr;
		console.log(arr[0]+","+arr[1]+","+arr[2]+","+arr[3]);
		
        //[3] 3개의 변수에 person 객체의 각각의 값 넣기
		var { name,age,job } = person;
		
		console.log(name);
		console.log(age);
		console.log(job);
		   
		//[4] map 이용 : arr배열의 요소들을 2로 나눈 나머지값을 새로운 배열로 만들어서 출력
		const newArray = arr.map((a,index)=>a%2);
		console.log(newArray);

 

 

 

 

템플릿 리터럴

 - 자바스크립트에서 문자열을 입력하는 방식

 - 기존 : var str = 'Hello ES6'  || ES6에서는 백틱 (back-tick)이라는 기호(`)를 사용하여 정의

 - 백틱을 이용하게 되면 여러 줄에 걸쳐 문자열을 정의할 수도 있고,

    자바스크립트의 변수를 문자열 안에 바로 연결할 수 있다.

const str = `Hello ES6`;

 

 

기존 : 여러 줄에 걸쳐 문자열 선언하기

var str = 'Template literals are string literals allowing embedded expressions. \n' + 
'You can use multi-line strings and string interpolation features with them. \n' + 
'They were called "template strings" in prior editions of the ES2015 specification.';

 - \n를 개행할 곳 중간 중간에 추가

 

 

 

백틱을 이용

  - 백틱을 이용해서 문자열을 선언하게 되면 개행할 필요가 없다

const str = `Template literals are string literals allowing embedded expressions.
You can use multi-line strings and string interpolation features with them.
They were called "template strings" in prior editions of the ES2015 specification.`;

 

 

 

 

 

import & Export

   - 자바스크립트의 코드를 모듈화 할 수 있는 기능

   - 다른 파일에 있는 자바스크립트의 기능을 특정 파일에서 사용할 수 있는 것