[JavaScript]-클로저(closure),주요문법

신보연·2023년 3월 6일
0

클로저(closure):

함수와 함수가 선언된 어휘적 환경의 조합.
클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.

MDN은 클로저를 아래와 같이 정의.
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). - mdn (2023)

어휘적 범위 지정(Lexical scoping):

"lexical" 이란 변수가 어디에서 사용 가능한지 알기 위해 그 변수가 소스코드 내 어디에서 선언되었는지를 고려한다는 것을 의미.

function init() {
  var name = "Mozilla"      // name은 init에 의해 생성된 지역변수
  
  function displayName() {   // displayName() 은 내부 함수이며, 클로저다.
    alert(name);             // 부모 함수에서 선언된 변수를 사용
  }
  
  displayName();
}

init();      // "Mozilla"를 알림창으로 실행

displayName()함수가 부모함수인 init()함수의 지역변수 var name을 가져다 씀.
따라서 함수가 중첩된 상황에서 파서가 어떻게 변수를 처리하는지 알 수 있다.
중첩된 함수는 외부 범위(scope)에서 선언한 변수에도 접근할 수 있다.


주요문법

spread 문법:

주로 배열을 풀어서 인자로 전달하거나, 배열을 풀어서 각각의 요소로 넣을 때에 사용.

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

sum(...numbers)

rest 문법:

파라미터를 배열의 형태로 받아서 사용할 수 있다. 파라미터 개수가 가변적일 때 유용.

function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

sum(1,2,3) 
sum(1,2,3,4)

배열에서 사용

  1. 배열 합치기
let parts = ['shoulders', 'knees'];
let lyrics = ['head', ...parts, 'and', 'toes'];
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

2.배열 복사

let arr = [1, 2, 3];
let arr2 = [...arr]; // arr.slice() 와 유사
arr2.push(4);  // 참고: spread 문법은 기존 배열을 변경하지 않으므로(immutable), arr2를 수정한다고, arr이 바뀌지 않는다.

객체에서 사용하기

let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };

let clonedObj = { ...obj1 };
let mergedObj = { ...obj1, ...obj2 };

함수에서 나머지 파라미터 받아오기

function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

구조분해할당

분해 후 새 변수에 할당

배열

const [a, b, ...rest] = [10, 20, 30, 40, 50];

객체

const {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
  • 객체에서 구조 분해 할당을 사용하는 경우, 선언(const, let, var)과 함께 사용하지 않으면 에러가 발생할 수 있다.

유용한 예제: 함수에서 객체 분해

function whois({displayName: displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

let user = {
  id: 42,
  displayName: "jdoe",
  fullName: {
      firstName: "John",
      lastName: "Doe"
  }
};

whois(user) 

화살표 함수:

화살표 함수는 ES6문법,
function 키워드 사용해서 함수를 만든 것보다 간단히 함수를 표현할 수 있다.

// 매개변수가 없는 경우
var foo = () => console.log('bar');
foo(); // bar

// 매개변수가 하나인 경우
var foo = x => x;
foo('bar'); // bar

// 매개변수가 여려개인 경우
var foo = (a, b) => a + b; // 간단하게 한줄로 표현할 땐 "{}" 없이 값이 반환.
foo(1, 2); // 3

var foo = (a, b) => { return a + b }; 
foo(1, 2); // 3

var foo = (a, b) => { a + b }; // "{}"를 사용했는데 return이 없을 때 
foo(1, 2); // undefined

var foo = (a, b) => { // 여러줄 썼을 때
	var c = 3;
	return a + b + c;
}
foo(1, 2, 3) // 6
/*
"{}"를 사용하면 값을 반환할 때 return을 사용해야함.
"{}"를 사용하지 않으면 undefied를 반환.
"{}"을 사용할 때는 여러줄을 썼을 때 사용.
*/

// 객체를 반환할 때
var foo = () => ( { a: 1, b: 2, c: 3 } );
foo(); // { a: 1, b: 2, c: 3 };

콜백 함수에서도 사용할 수 있다.

// ES5
var numbers = [1, 4, 9];
var oddArr = numbers.filter(function (x) { return x % 2 !== 0;});
console.log(oddArr); // [1, 9]
// ES6
var numbers = [1, 4, 9];
var oddArr = numbers.filter( x => (x % 2) !== 0 );
console.log(oddArr); // [1, 9]

화살표 함수 this:

일반 함수와 화살표 함수의 차이점이 있다. 일반함수가 전역 컨텍스트에서 실행될 때 this가 정의, 화살표함수는 this를 정의하지 않는다.

함수의 내부함수, 콜백함수에 사용되는 this는 window이다.

0개의 댓글