.png)
특정 갯수의 인자(매개변수)를 필요로 하는 함수에 함수 실행문에서의 인수를 인자 갯수보다 적게 보내면 함수는 undefined를 반환하지만 인자보다 인수가 더 많아서 인수가 남는 경우에 남는 변수를 나머지 매개변수(Rest parameters)라고 한다.
여러 번 사용되는 함수인데 인수의 개수가 특정 지어지지 않았을 때 사용되며 나머지 매개변수는 인자를 배열 형태로 받는 형식이다
(나머지 매개변수는 배열의 메소드 사용이 가능하다.(length(), reduce(), 등등...)
ex) 인수로 보내는 모든 수를 더하는 함수.
function addAll(...nums){
let result = 0;
nums.forEach(num => (result += num));
return result;
}
console.log(addAll(1,2,3)); // 6
console.log(addAll(4,5,6)); // 15
ex) 생성자 함수 프로퍼티에 값이 하나가 아닐 때.
function User(name, age, ...skills){
this.name = name;
this.age = age;
this.skills = skills;
}
let user1 = new User("Mike", 30, "HTML", "CSS");
let user2 = new User("Wonseo", 26, "JS", "React");
let user3 = new User("Sam", 20, "Java");
console.log(user1) // User { name: 'Mike', age: 30, skills: [ 'HTML', 'CSS' ] }
console.log(user2) // User { name: 'Wonseo', age: 26, skills: [ 'JS', 'React' ] }
console.log(user3) // User { name: 'Sam', age: 20, skills: [ 'Java' ] }
나머지 매개변수는 인자에서 항상 마지막에 위치하여야 한다.
(오류 초래) Rest parameter must be last formal parameter]
전개구문 (Spread Syntax)이란 나머지 매개변수처럼 ...변수명의 형태로 생겼으나 생김새는 많이 다르다.
아래의 예로 간단히 살펴보겠다.
전개구문을 이용하여 한 객체의 모든 내용을 다른 객체 안에 집어넣기
const user1 = {name : "Mike"};
const user2 = {...user1, age : 30}; // user1 객체의 내용을 user2 객체 내 앞 부분에 삽입
user2.name = "Sam"
console.log(user1); // { name: 'Mike' }
console.log(user2); // { name: 'Sam', age: 30 }
배열 내에 순서를 건드리지 않고 배열 끼리의 순서를 바꿔 집어넣기
let arr1 = [1,2,3];
const arr2 = [4,5,6];
arr1 = [...arr2, ...arr1]; // arr1 배열 안에 전개 구문을 이용하여 arr2 배열을 넣고 그 뒤에 arr1을 넣음
console.log(arr1); // [ 4, 5, 6, 1, 2, 3 ]
객체와 배열 형태들을 한 객체 안에 저장할 때
let user = {name : "Mike"};
let info = {age : 30};
let fe = ["JS", "React"];
let lang = ["Korean", "English"];
user = {
user, // user 객체 내용을 넣고
info, // info 객체 내용을 넣고
skills : [...fe, ...lang] // skills 프로퍼티의 배열 값 안에는 fe와 lang의 모든 정보를 전개구문을 통하여 집어넣음
};
console.log(user);
// {
// user: { name: 'Mike' },
// info: { age: 30 },
// skills: [ 'JS', 'React', 'Korean', 'English' ]
// }
자바스크립트는 어휘적 환경(Lexical Enviroment)을 갖는다.
//스크립트 시작 준비 단계 (1)
let one; // (2)
one = 1; // (3)
function addOne(num){
console.log( one + num );
}
addOne(5); // (4)
해당 스크립트를 실행하였을 Lexical 환경의 변화는 아래와 같다.
(1) one : 초기화X [현재 사용불가]
addOne:function 이 Lexical 환경에 올라간다.
(2) 본격적으로 위에서부터 아래로 읽어내림
one : undefined [사용 가능]
addOne : function
(3) one : 1
addOne : function
(4) 함수를 실행하며 새로운 Lexical 환경 생성
내부 Lexical 환경 (함수를 실행하여 생성된 Lexical 환경)
함수가 넘겨받은 매개변수와 지역변수들이 저장 되어 있음.
num :5
전역 Lexical 환경 (기존에 존재하던 Lexical 함수)
전역 스코프의 변수와 함수가 저장되어 있음.
one : 1
addOne : function
내부 Lexical 환경은 전역 Lexical 환경을 참조하고 있음.
다만, 내부 Lexical 환경이 참조하는 바로 위 상위 값은 늘 전역 Lexical 환경은 아니고 상위 함수의 Lexical 환경을 참조할 수 있음.
예를 들면, addOne()함수 실행 시에 해당 함수 표현식대로 동작을 할 때에 num은 내부 Lexical 환경에 존재하여 바로 찾을 수 있지만 one은 내부 Lexical 환경에 존재하지 않아 참조하는 외부의 전역 Lexical 환경에서 변수를 가져옴
마무리로 예를 들며 어휘적 환경을 마무리 하도록 하겠다.
function makeAdder(x){
return function(y){
return x+y;
};
}
const add3 = makeAdder(3);
console.log(add3(2));
순차 설명)
1. 전역 Lexical 환경에서 makeAdder()와 add3 상수를 선언 함.
2. const add3에 할당되는 makeAdder(3) 실행
3. 해당 함수는 add3에 makeAdder에서 return 되는 함수를 할당 하며 makeAdder Lexical 환경을 생성하며 안에는 x : 3의 값을 가지고 있음.
const add3 = function(y){
return 3 + y;
}
해당 함수가 add3에 할당되는 구조.
4. console.log()안에서 add3(2)가 실행 되며 add3의 Lexical 환경이 생성되며 y : 2의 값을 가지고 있음.
x + y의 계산을 할 때에 x는 add3의 Lexical 환경에 존재하지 않기에 상위에 참조하는 makeAdder의 Lexical 환경에서 x의 값을에 접근하고 y의 값은 해당 add3의 Lexical 환경에서 참조하여 3 + 2(y인자)를 반환하여 콘솔 창에 5가 출력 됨.
이 함수는 생성될 당시의 외부 변수(전역 변수, 상위 함수의 Lexical 환경이 가지는 변수)를 기억하여 이후에도 계속 접근이 가능 한 이러한 함수와 Lexical 환경의 조합을 Closure 라고 한다.
SetTimeout은 일정 시간이 지난 후 함수를 실행하는 것이다.
function fn(){
console.log("타임 아웃");
}
setTimeout(fn, 3000); // 3초 뒤 fn() 함수 실행
----------------------------------
setTimeout(function(){
console.log(3);
}, 3000); //위와 동일하게 작동(함수를 안에 작성)
-----------------------------------
function showName(name){
console.log(name);
}
setTimeout(showName, 3000, "Mike");
// 실행 할 함수의 인수가 필요하다면 setTimeout의 인수의 맨 뒤에 넣어주면 된다.
인수로 동작할 함수와 실행 후 동작까지의 시간을 받는다.
같이 사용하는 함수로는 ClearTimeout(tId);이 있다.
const myTimeout = setTimeout((fn)=>console.log(`Time ${fn} !!`), 3000, "Out");
clearTimeout(myTimeout);
이 처럼 setTimeout은 값을 반환하는데 해당 값을 할당하여 해당 setTimeout의 이름처럼 사용할 수 있다.
값을 할당받은 변수를 clearTimeout에 인수로 넣어주면 해당 setTimeout의 실행을 막는다.
setInterval은 일정 시간 간격으로 함수를 반복하는 것이다.
const myInterval = setInterval((fn)=>console.log(`Time ${fn} !!`), 3000, "Interval");
clearInterval(myInterval);
setTimeInterval은 위처럼 setTimeout과 문법은 같다.
해당 함수들의 간단한 예로는
let num = 0;
function showTime(){
console.log(`안녕하세요, 현재 접속하신지 ${num++}초 됐습니다.`);
if(num > 5){
clearInterval(tId);
}
}
const tId = setInterval(showTime, 1000);
//안녕하세요, 현재 접속하신지 0초 됐습니다.
//안녕하세요, 현재 접속하신지 1초 됐습니다.
//안녕하세요, 현재 접속하신지 2초 됐습니다.
//안녕하세요, 현재 접속하신지 3초 됐습니다.
//안녕하세요, 현재 접속하신지 4초 됐습니다.
//안녕하세요, 현재 접속하신지 5초 됐습니다.
// [num이 5가 넘었으므로 종료된다.]