📝 TIL
[TIL] JS 함수, 클로저, call(), apply(), bind(), 구조분해할당
오늘 ONEUL
2022. 4. 22. 21:31
✍ Today I Learned
[함수 Functions]
- 익명 함수란? 말 그대로 이름이 없는 함수. 예를 들면 함수 표현식에서 사용되는 함수는 변수를 통해 호출하기 때문에 함수 이름이 필요하지 않다.
const x = function (a, b) {return a * b};
let z = x(4, 3);
- 함수를 만들어내는 자바스크립트 내장 함수
Function()
생성자를 사용하여 함수를 만들 수도 있다. 그러나 위의 익명 함수 코드와 동일하게 작동하기 때문에 굳이 사용할 필요는 없다.
const myFunction = new Function("a", "b", "return a * b");
let x = myFunction(4, 3);
- 자바스크립트는 초기화가 아닌 선언만 호이스팅 되기 때문에 변수 선언은 시작 부분에서 하는 것이 좋다.
- 함수 표현식, 화살표 함수는 호이스팅 되지 않는다.
- 화살표 함수의 this는 상위 환경의 this를 가리킨다.
- 자체 호출 함수(Self invoking)는 호출 없이 자동으로 실행된다. 먼저 실행되어야 하는 세팅값이나, 클로저에 사용된다.
(function () {
let x = "Hello!!"; // I will invoke myself
})();
[매개변수와 전달 인자 Parameter & Arguments]
- parameter - 정의된 함수에 나열된 변수
- arguments - 함수에 전달되는 실제 값
- 자바스크립트에서는 parameter의 타입을 따로 명시하지 않고, argument로 전달된 값에 대해 어떤 타입 검사도 하지 않는다.
- 함수를 호출할 때 함수의 정의보다 적은 인수가 전달되더라도 오류를 발생시키지 않고, 전달되지 않은 값은 undefined를 설정한다.
- 위와 같은 경우, parameter에 별도로 기본값을 설정할 수 있다 -> Optional Parameter
function multiply(a, b = 1) {
return a*b
}
multiply(5, 2) // 10
multiply(5) // 5
multiply(5, undefined) // 5
- Optional Parameter는 항상 parameter의 가장 마지막에 설정해야 한다.
- 자바스크립트 함수에는 arguments라는 내장 객체가 있다. 함수가 호출될 때 전달된 인수를 배열의 형태로 저장한다. (실제 Array 객체는 아님)
- arguments 객체에 Optional Parameter의 값은 저장되지 않는다.
- Rest Parameter - 생략 접두사(...)를 사용하여 특정 위치의 인수부터 마지막 인수까지를 한 번에 지정한다. 함수 내부에서 재할당 및 연산을 위해 필요한 파라미터와 값만 전달받는 파라미터를 분리하여 사용해야 할 때 편리하다.
function restParamFunc(a, b, ...others) {
console.log(a + b);
console.log(others);
for (const arg of others) {
console.log(`others : ${arg}`);
}
}
restParamFunc(10, 20, 30, 40, 50); // 30, [30, 40, 50], others: 30...
[함수 호출 Invocation]
- 소속된 객체 없이 전역에서 함수를 호출할 경우 this는 전역 객체가 된다. 웹 브라우저 전역 객체는 window 객체이다.
- 객체에 소속된 함수를 할 경우 this는 소속된 객체 자체가 된다.
[함수 클로저 Closures]
- Closures(클로저) - 함수와 함수가 선언된 어휘적 환경의 조합이다. 핵심은 스코프를 이용하여 변수의 접근 범위를 닫는(폐쇄)것이다.
- 변수에 self-invoking을 할당하고, 외부 함수의 리턴 값으로 내부 함수를 할당하여 전역 변수처럼 활용할 수 있다.
const add = (function () {
let counter = 0;
return function () {counter += 1; return counter}
})();
add();
add();
add();
// 현재 count는 3이다.
- 클로저는 외부 함수가 닫힌 후에도 외부 함수 내 변수에 접근할 수 있는 함수이다.
[call()
메서드]
func.call(thisArg, arg1, arg2)
- 이미 할당되어있는 다른 객체의 함수, 메서드를 호출하는 해당 객체에 재할당할 때 사용된다. thisArg는 func호출에 제공되는 this의 값이다.
const person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
const person1 = {
firstName:"John",
lastName: "Doe"
}
person.fullName.call(person1, "Oslo", "Norway");
[apply()
메서드]
func.apply(thisArg, \[argArray\])
-call()
메서드와 유사하다.call()
메서드와apply()
메서드의 차이점은?call()
메서드는 인수를 별도로 사용하고,apply()
메서드는 인수를 배열로 사용한다.
const person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
const person1 = {
firstName:"John",
lastName: "Doe"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);
- 저번 json_iteration 2번 문제에서 배열의 최댓값을 return 받기 위해 사용했던 function이
apply()
를 사용한 function이었다..! 배열에는max()
라는 메서드가 없기 때문에apply()
를 이용해서 대신 적용할 수 있다.
function myArrayMax(arr) {
return Math.max.apply(null, arr);
}
[bind()
메서드]
func.bind(thisArg, arg1, arg2)
- 이미 할당되어있는 다른 객체의 함수, 메서드를 호출하는 해당 객체로 빌려와 실행시킬 때 사용된다.call()
메서드와apply()
메서드는 내가 뭔가를 시키는 개념,bind()
메서드는 빌려서 가져오는 개념.- 할당된 변수를 함수호출식으로 실행하면 데이터 객체의 메서드처럼 실행된다.
bind()
메서드는 로드 시점과 실행 시점이 다르기 때문에setTimeout(callback, duration)
과 같이 실행 시차를 가지는 함수에서 this 키워드를 사용하더라도 데이터 객체를 그대로 참조할 수 있다.
const person = {
firstName:"John",
lastName: "Doe",
display: function () {
let x = document.getElementById("demo");
x.innerHTML = this.firstName + " " + this.lastName;
}
}
let display = person.display.bind(person);
setTimeout(display, 3000);
[구조 분해 할당 Destructuring assignment]
- 구조 분해 할당이란? 함수에 객체나 배열을 전달해야 하는 경우, 객체나 배열에 저장된 데이터의 전체가 아닌 일부만 필요한 경우에 객체나 배열을 변수로 '분해’할 수 있게 해주는 특별한 문법이다.
// 이름과 성을 요소로 가진 배열
let arr = ["Eunsol", "An"]
// 구조 분해 할당을 이용해
// firstName엔 arr[0]을
// surname엔 arr[1]을 할당
let [firstName, surname] = arr;
alert(firstName); // Eunsol
alert(surname); // An