1. null 병합 연산자(nullish coalescing operator) 

 

  ??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 ‘확정되어있는’ 변수를 찾을 수 있다.

 

  a ?? b의 평가 결과는 다음과 같습니다.

  • a가 null도 아니고 undefined도 아니면 a
  • 그 외의 경우는 b

  다음 예시를 통해 살펴보자.

 

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// null이나 undefined가 아닌 첫 번째 피연산자
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

 

 

 

2. '||' 와 '??'의 차이

 

  null 병합 연산자는 OR 연산자 ||와 상당히 유사하다.

  실제로 위 예시에서 ??를 ||로 바꿔도 그 결과는 동일하다.

  그런데 두 연산자 사이에는 중요한 차이점이 있다.

 

  • ||는 첫 번째 truthy 값을 반환한다.
  • ??는 첫 번째 정의된(defined) 값을 반환한다.

  null과 undefined, 숫자 0을 구분 지어 다뤄야 할 때 이 차이점은 매우 중요한 역할을 한다.

  예시를 살펴보자.

 

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0

 

  height 변수에는 0이라는 number type의 data가 할당되어있다. 즉 정의된 값이다.

  하지만 || 연산자는 첫 번째 값이 falsy 하다면 false로 간주한다.

  자바스크립트에는 6가지 falsy한 값이 있다. null, undefined, 0, 빈 문자열, NaN, false가 그것이다.

  그렇기 때문에 100을 출력한다.

 

  반면 ?? 연산자는 그 값이 falsy 하다하더라도 정의된 값이면 해당 값을 반환하기 때문에 0을 출력한다.

  즉 height가 null과 undefined일때만 100을 출력할 것이다.

 

 

 

3. 연산자 우선순위와 주의사항

 

  '??'의 연산자 우선순위는 5로 꽤 낮다.

  따라서 ??는 =와 ? 보다는 먼저, 대부분의 연산자보다는 나중에 평가된다.

  그렇기 때문에 복잡한 표현식 안에서 ??를 사용해 값을 하나 선택할 땐 괄호를 추가하는 게 좋다.

 

  또한 주의사항으로는 안정성 관련 이슈 때문에 ??는 &&나 ||와 함께 사용하지 못합니다.

  아래 예시를 실행하면 문법 에러가 발생한다.

 

let x = 1 && 2 ?? 3; // SyntaxError: Unexpected token '??'

//제약을 피하려면 괄호를 사용해주세요.

let x = (1 && 2) ?? 3; // 제대로 동작합니다.

alert(x); // 2

 

 

 

*출처 : ko.javascript.info/nullish-coalescing-operator#ref-138

'Programming Language > Javascript' 카테고리의 다른 글

ES6 - 함수 표현식, 화살표 함수  (0) 2021.01.09
ES6 - Promise & Async/Await  (0) 2021.01.04
ES6 - 구조 분해 할당  (0) 2020.12.31
ES6 - Class(1)  (0) 2020.12.29
Rest Parameter & Spread Syntax  (0) 2020.11.06

1. 함수 표현식

 

let sayHi = function() {
  alert( "Hello" );
};

 

  자바스크립트에선 다음과 같이 변수에 함수를 할당할 수 있다. 이와같이 변수에 함수가 할당된 것을 함수 표현식이라고 한다.

  그렇다면 왜 자바스크립트에선 다른 언어와 달리 함수 표현식으로 나타내는 것이 가능할까?

  그것은 바로 자바스크립트가 함수를 값으로 취급하기 때문이다.

 

  즉, 함수를 다른 변수와 동일하게 다룰 수 있다는 의미이다. 이와 같은 언어를 일급 함수를 가졌다고 표현한다.

  일급 함수를 가진 언어에서는 함수를 다른 함수에 매개변수로 제공하거나, 함수가 함수를 반환할 수 있으며, 변수에도 할당할 수 있다.

 

 

 

2. 콜백 함수

 

  앞서 자바스크립트에서는 다른 함수의 매개 변수로 함수를 제공할 수 있다고 했다.

  아래 예시를 살펴보자.

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function showOk() {
  alert( "동의하셨습니다." );
}

function showCancel() {
  alert( "취소 버튼을 누르셨습니다." );
}

// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);

  

  ask함수의 인수로 showOk, showCancel 이라는 함수가 전달됐고 confirm(question)의 결과에 따라 해당 함수를 실행함을 알 수 있다.

  이처럼 어떤 함수가 다른 함수의 인수로 전달되어 특정 동작후에 나중에 호출되는 함수를 콜백 함수라 한다.

  너가 특정 동작을 한 후에 나를 호출해줘라는 의미에서 call back이라 부르는 것이다.

 

 

 

3. 함수 표현식 vs 함수 선언문

 

  첫 번째 차이는 기본적인 문법의 차이이다.

 

function sum(a, b) {
  return a + b;
} //함수 선언문

let sum = function(a, b) {
  return a + b;
}; //함수 표현식

 

  두 번째 차이는 자바스크립트 엔진이 언제 함수를 생성하는지에 있다.

  함수 표현식은 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성한다.

  따라서 실행 흐름이 함수에 도달했을 때부터 해당 함수를 사용할 수 있다.

 

  하지만 함수 선언문은 조금 다르다.

  함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있다.

  이것이 가능한 이유는 자바스크립트 엔진이 변수 선언, 함수 선언문을 스크립트의 젤 위로 먼저 위치시키기 때문이다.

  이것을 Hoisting이라고 한다.

  따라서 스크립트는 함수 선언문을 먼저 처리한 이후에서야 나머지 코드를 실행한다.

  따라서 스크립트 어디서든 함수 선언문으로 선언한 함수에 접근할 수 있는 것이다.

 

 

 

4. Arrow function(화살표 함수)

 

  화살표 함수는 문법의 생김새에 따라 이름이 지어졌다.

  굳이 구분할 것도 없지만 처음에 나도 화살표 함수를 접할 때 굉장히 익숙하지 않아서 적응하는데 애를 먹었다.

  화살표 함수는 크게 세 가지 형태만 기억하면 된다.

 

  4 - 1) 인수가 하나밖에 없다면 인수를 감싸는 괄호를 생략할 수 있다. 괄호를 생략하면 코드 길이를 더 줄일 수 있다.

 

let double = n => n * 2;
// let double = function(n) { return n * 2 }과 동일하다.

alert( double(3) ); // 6

 

  4 - 2) 인수가 하나도 없을 땐 괄호를 비워놓으면 된다. 다만, 이 때 괄호는 생략할 수 없다.

 

let sayHi = () => alert("안녕하세요!");

sayHi();

 

  4 - 3) 평가해야 할 표현식이나 구문이 여러 개인 함수가 있을 수도 있다.

 

    이때는 중괄호 안에 평가해야 할 코드를 넣어주어야 한다.

    그리고 return 지시자를 사용해 명시적으로 결괏값을 반환해 주어야 한다.

let sum = (a, b) => {  // 중괄호는 본문 여러 줄로 구성되어 있음을 알려줍니다.
  let result = a + b;
  return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해주어야 합니다.
};

alert( sum(1, 2) ); // 3

 

 

 

*출처 : ko.javascript.info/function-expressionsko.javascript.info/arrow-functions-basics, developer.mozilla.org/ko/docs/Glossary/First-class_Function

'Programming Language > Javascript' 카테고리의 다른 글

ES11 - null 병합 연산자 '??'  (0) 2021.01.09
ES6 - Promise & Async/Await  (0) 2021.01.04
ES6 - 구조 분해 할당  (0) 2020.12.31
ES6 - Class(1)  (0) 2020.12.29
Rest Parameter & Spread Syntax  (0) 2020.11.06

1. 소개

 

  이미지를 가져와서 압축하고 필터를 적용하고 저장하고 싶다고 가정해보자.

  가장 먼저 해야 할 일은 편집할 이미지를 가져오는 것이다. getImage 함수가 이를 처리할 수 ​​있다.

 

  이미지가 성공적으로 로드된 후에만 ​​해당 값을 resizeImage 함수에 전달할 수 있다.

 

  이미지 크기가 성공적으로 조정되면 applyFilter 함수에서 이미지에 필터를 적용하려고 할 것이다.

 

  이미지를 압축하고 필터를 추가한 후 이미지를 저장하고 모든 것이 올바르게 작동했음을 사용자에게 알리고 싶다!

  결국 우리는 다음과 같은 코드를 얻게 될 것이다.

 

Nested Callback

 

  위 코드를 보면 콜백 함수에 의존하는 많은 중첩 콜백 함수로 코드를 작성했다.

  이것은 코드를 읽기 어렵게 만드는 수많은 중첩된 콜백 함수로 끝나기 때문에 종종 콜백 지옥이라고 한다!

 

  다행히도 이제 우리를 도울 수 있는 Promise이라는 것이 생겼다!

  Promise이 무엇인지, 이러한 상황에서 어떻게 우리를 도울 수 있는지 살펴보자!

 

 

 

2. Promise Syntax

  

  프로미스는 생성자에 의해 생성된 프로미스 객체는 두 가지의 프로퍼티를 가진다.

  바로 state, value 프로퍼티이다.

 

  2 - 1) Promise State : 프로미스는 크게 세 가지 상태를 가진다.

  • Pending : 약속이 이행되지도 않았고 그렇다고 거부된 것도 아닌 상태
  • Fullfiled : 약속이 이행된 상태
  • Rejected : 에러가 있거나 어떤 문제로 인해 약속이 거부된 상태
let promise = new Promise((resolve, reject) => {
	//new Promise에 전달되는 함수는 executor(실행 함수) 라고 부른다.
    //executor의 인수 resolve와 reject는 자바스크립트가 자체적으로 제공하는 콜백함수다. 
    //개발자는 resolve와 reject를 신경 쓰지 않고 executor 안 코드만 작성하면 된다.
    //다만, resolve나 reject 중 하나는 반드시 호출해야 한다.
    //state는 resolve가 호출되면 "fulfilled", reject가 호출되면 "rejected"로 변한다.
    //executor는 보통 시간이 걸리는 일을 수행한다 즉 비동기적으로 수행되는 일을 의미. 
    //일이 끝나면 resolve나 reject 함수를 호출하는데, 이때 프라미스 객체의 상태가 변화합니다.
    //이행(resolved)되거나 거부(rejected)된 상태의 프라미스는 ‘처리된(settled)’ 프라미스라고 부릅니다. 
    //반대되는 프라미스로 '대기(pending)'상태의 프라미스가 있습니다.
    resolve('promise')
})

 

  2 - 2) Promise Value : 프로미스의 상태에 따라 Value 값이 달라짐.

   

    즉, promise의 value는 resolve 메서드나 reject 메서드에 인수로 전달하는 값이 된다.

    위 예시에서는 'promise'가 value가 될 것이다.

 

 

 

  2 - 3) 소비자 메서드

 

    마지막으로, 우리는 전체 promise 객체를 다루지 않고 promise에 의해 해결된 value만을 활용하고 싶을 것이다.

    그때 아래 세 가지 메서드를 활용할 수 있다.

 

  • . then : resolve 메서드에 의해 받은 value를 인자로 받는다.
  • . catch : reject 메서드에 의해 받은 value를 인자로 받는다.
  • . finally : resolve, reject 메서드에 의해 받은 value를 인자로 받는다

  .then의 첫 번째 인수는 프라미스가 이행되었을 때 실행되는 함수이고, 여기서 실행 결과를 받는다.

  .then의 두 번째 인수는 프라미스가 거부되었을 때 실행되는 함수이고, 여기서 에러를 받는다.

  

  .then

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
});

// resolve 함수는 .then의 첫 번째 함수(인수)를 실행합니다.
promise.then(
  result => alert(result), // 1초 후 "done!"을 출력
  error => alert(error) // 실행되지 않음
);

//작업이 성공적으로 처리된 경우만 다루고 싶다면 .then에 인수를 하나만 전달하면 됩니다.

let promise = new Promise(resolve => {
  setTimeout(() => resolve("done!"), 1000);
});

promise.then(alert); // 1초 뒤 "done!" 출력

 

 

 

  . catch

//에러가 발생한 경우만 다루고 싶다면 .then(null, errorHandlingFunction)같이 
//null을 첫 번째 인수로 전달하면 됩니다. .catch(errorHandlingFunction)를 써도 되는데, 
//.catch는 .then에 null을 전달하는 것과 동일하게 작동합니다.

let promise = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error("에러 발생!")), 1000);
});

// .catch(f)는 promise.then(null, f)과 동일하게 작동합니다
promise.catch(alert); // 1초 뒤 "Error: 에러 발생!" 출력
//.catch(f)는 문법이 간결하다는 점만 빼고 .then(null,f)과 완벽하게 같습니다.

  

 

 

3. Promise Chaining

 

  콜백 지옥 예제에서는 콜백을 실행하기 위해 여러 개의 콜백을 중첩해야 했다.

  다행히. then 핸들러가 도움을 줄 수 있다!. then 자체의 결과는 약속 값이다.

  이것은 우리가 원하는 만큼 많은. thens를 연결할 수 있음을 의미한다.

  이전 then 콜백의 결과가 다음 then 콜백에 대한 인수로 전달되기 때문이다!

 

Promise chaining

 

  어떤가? 콜백 지옥으로 가독성이 떨어진 코드보다 Promise Syntax로 인해 코드가 훨씬 명료해졌음을 알 수 있다.

 

 

 

4. Async/Await

 

  Async/Await 문법은 JavaScript에서 비동기 동작을 추가하고 promise 작업을 더 쉽게 만드는 새로운 방법이다!

  async 및 await 키워드를 도입하여 암시 적으로 promise를 반환하는 비동기 함수를 만들 수 있다.

  이전에는 new Promise (() => {}), Promise 객체를 사용하여 명시 적으로 promise를 만들 수 있음을 확인했다.

  Promise 객체를 명시 적으로 사용하는 대신 이제 암시적으로 객체를 반환하는 비동기 함수를 만들 수 있다!

  이것은 우리가 더 이상 Promise 객체를 직접 작성할 필요가 없음을 의미한다.

 

  비동기 함수가 암시적으로 promise를 반환한다는 사실은 꽤 훌륭하지만 await 키워드를 사용하면 비동기 함수의 진정한 힘을 볼 수 있다!    await 키워드를 사용하면 awaited 값이 해결된 promise를 반환할 때까지 기다리는 동안 비동기 함수를 일시 중단할 수 있다.

  이전에 then () 콜백에서 했던 것처럼 이 해결된 promise의 값을 얻으려면 대기된 promise 값에 변수를 할당할 수 있다!

 

  4 - 1) async 함수

 

    function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다.

    프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다.

 

async function f() {
  return 1;
}

f().then(alert); // 1
//명시적으로 프라미스를 반환하는 것도 가능한데, 결과는 동일합니다.

async function f() {
  return Promise.resolve(1);
}

f().then(alert); // 1

 

  async가 붙은 함수는 반드시 프라미스를 반환하고, 프라미스가 아닌 것은 프라미스로 감싸 반환한다. 

  그런데 async가 제공하는 기능은 이뿐만이 아니다.

  또 다른 키워드 await async 함수 안에서만 동작합니다. 

  await는 아주 멋진 녀석이다.

 

  자바스크립트는 await 키워드를 만나면 프라미스가 처리(settled)될 때까지 기다린다.

  결과는 그 이후 반환된다. 1초 후 이행되는 프라미스를 예시로 사용하여 await가 어떻게 동작하는지 살펴보자.

 

async function f() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("완료!"), 1000)
  });

  let result = await promise; // 프라미스가 이행될 때까지 기다림 (*)

  alert(result); // "완료!"
}

f();

 

  함수를 호출하고, 함수 본문이 실행되는 도중에 (*)로 표시한 줄에서 실행이 잠시 '중단’되었다가 프라미스가 처리되면 실행이 재개된다.

  이때 프라미스 객체의 result 값이 변수 result에 할당된다. 따라서 위 예시를 실행하면 1초 뒤에 '완료!'가 출력된다.

 

  await는 말 그대로 프라미스가 처리될 때까지 함수 실행을 기다리게 만든다. 프라미스가 처리되면 그 결과와 함께 실행이 재개된다.

  프라미스가 처리되길 기다리는 동안엔 엔진이 다른 일을 할 수 있기 때문에, CPU 리소스가 낭비되지 않는다.

 

  await는 promise.then보다 좀 더 세련되게 프라미스의 result 값을 얻을 수 있도록 해주는 문법이다. 

  promise.then보다 가독성 좋고 쓰기도 쉽다.

 

  * 주의사항 : async 함수가 아닌데 await을 사용하면 문법 에러가 발생한다.

 

  async/await를 함께 사용하면 읽고, 쓰기 쉬운 비동기 코드를 작성할 수 있다.

  async/await를 사용하면 promise.then/catch가 거의 필요 없다.

 

  하지만 가끔 가장 바깥 스코프에서 비동기 처리가 필요할 때같이 promise.then/catch를 써야만 하는 경우가 생기기 때문에 async/await가 프라미스를 기반으로 한다는 사실을 알고 있어야 한다.

 

  즉 async/await syntax는 promise syntax의 syntatic sugar라고 할 수 있다!

 

 

 

출처 : ko.javascript.info/async, dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke

'Programming Language > Javascript' 카테고리의 다른 글

ES11 - null 병합 연산자 '??'  (0) 2021.01.09
ES6 - 함수 표현식, 화살표 함수  (0) 2021.01.09
ES6 - 구조 분해 할당  (0) 2020.12.31
ES6 - Class(1)  (0) 2020.12.29
Rest Parameter & Spread Syntax  (0) 2020.11.06

1. 구조 분해 할당이란?

 

  객체와 배열은 자바스크립트에서 가장 많이 쓰이는 자료 구조다.

  개발을 하다 보면 함수에 객체나 배열을 전달해야 하는 경우가 있다.

  가끔은 객체나 배열에 저장된 데이터 전체가 아닌 일부만 필요한 경우가 생기기도 한다.

  이럴 때 객체나 배열을 변수로 '분해’할 수 있게 해주는 특별한 문법인 구조 분해 할당(destructuring assignment) 을 사용할 수 있다.

  이 외에도 함수의 매개변수가 많거나 매개변수 기본값이 필요한 경우 등에서 구조 분해(destructuring)는 그 진가를 발휘한다.

 

 

2. 배열 분해하기

  

1
2
3
4
5
6
7
let arr = ["Bora""Lee"]
 
// 구조 분해 할당을 이용해
// firstName엔 arr[0]을
// surname엔 arr[1]을 할당하였습니다.
let [firstName, surname] = arr;
console.log(firstName) // "Bora"
cs

 

  구조 분해 할당이란 명칭은 어떤 것을 복사한 이후에 변수로 '분해(destructurize)'해준다는 의미 때문에 붙여졌다.

  이 과정에서 분해 대상은 수정 또는 파괴되지 않는다.

 

  또한 아래의 예와 같이 쉼표를 사용하면 필요하지 않은 배열 요소를 버릴 수 있다

 

1
2
3
let [firstName, , title] = ["Julius""Caesar""Consul""of the Roman Republic"];
//두 번째 요소는 생략되었지만, 세 번째 요소는 title이라는 변수에 할당된 것을 확인할 수 있습니다. 
//할당할 변수가 없기 때문에 네 번째 요소 역시 생략되었습니다
cs

 

  할당 연산자 좌측엔 ‘할당할 수 있는(assignables)’ 것이라면 어떤 것이든 올 수 있다.

  아래와 같이 객체 프로퍼티도 가능하다.

 

1
2
let user = {};
[user.name, user.surname] = "Bora Lee".split(' ');
cs

 

  배열 앞쪽에 위치한 값 몇 개만 필요하고 그 이후 이어지는 나머지 값들은 한데 모아서 저장하고 싶을 때가 있다.

  이럴 때는 점 세 개 ...를 붙인 매개변수 하나를 추가하면 ‘나머지(rest)’ 요소를 가져올 수 있다.

 

1
2
3
4
5
6
7
let [name1, name2, ...rest] = ["Julius""Caesar""Consul""of the Roman Republic"];
 
alert(name1); // Julius
alert(name2); // Caesar
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2
cs

 

  rest는 나머지 배열 요소들이 저장된 새로운 배열이 된다. 

  rest 대신에 다른 이름을 사용해도 되는데, 변수 앞의 점 세 개(...)와 변수가 가장 마지막에 위치해야 한다는 점은 잊지말자.

 

 

 

3. 객체 분해하기

 

  프로퍼티 options.title options.width, options.height에 저장된 값이 상응하는 변수에 할당된 것을 확인할 수 있다.

  참고로 순서는 중요하지 않습니다. 아래와 같이 작성해도 위 예시와 동일하게 동작한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let options = {
  title: "Menu",
  width: 100,
  height: 200
};
 
let {title, width, height} = options;
 
alert(title);  // Menu
alert(width);  // 100
alert(height); // 200
 
// let {...} 안의 순서가 바뀌어도 동일하게 동작함
let {height, width, title} = { title: "Menu", height: 200, width: 100 }
cs

 

  프로퍼티가 없는 경우를 대비하여 =을 사용해 기본값을 설정하는 것도 가능하다.

 

1
2
3
4
5
6
7
8
9
let options = {
  title: "Menu"
};
 
let {width = 100, height = 200, title} = options;
 
alert(title);  // Menu
alert(width);  // 100
alert(height); // 200
cs

 

  나머지 패턴(rest pattern)을 사용하면 배열에서 했던 것처럼 나머지 프로퍼티를 어딘가에 할당하는 게 가능하다.

  참고로 IE를 비롯한 몇몇 구식 브라우저는 나머지 패턴을 지원하지 않으므로 주의해서 사용해야 한다.

  물론 바벨(Babel)을 이용하면 되지만요.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
let options = {
  title: "Menu",
  height: 200,
  width: 100
};
 
// title = 이름이 title인 프로퍼티
// rest = 나머지 프로퍼티들
let {title, ...rest} = options;
 
// title엔 "Menu", rest엔 {height: 200, width: 100}이 할당됩니다.
alert(rest.height);  // 200
alert(rest.width);   // 100
cs

 

 

 

4. 중첩 구조 분해

 

  객체나 배열이 다른 객체나 배열을 포함하는 경우, 좀 더 복잡한 패턴을 사용하면 중첩 배열이나 객체의 정보를 추출할 수 있다.

  이를 중첩 구조 분해(nested destructuring)라고 부른다.

  아래 예시에서 객체 options의 size 프로퍼티 값은 또 다른 객체다. 

  items 프로퍼티는 배열을 값으로 가지고 있다.

  대입 연산자 좌측의 패턴은 정보를 추출하려는 객체 options와 같은 구조를 갖추고 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let options = {
  size: {
    width: 100,
    height: 200
  },
  items: ["Cake""Donut"],
  extra: true
};
 
// 코드를 여러 줄에 걸쳐 작성해 의도하는 바를 명확히 드러냄
let {
  size: { // size는 여기,
    width,
    height
  },
  items: [item1, item2], // items는 여기에 할당함
  title = "Menu" // 분해하려는 객체에 title 프로퍼티가 없으므로 기본값을 사용함
= options;
 
alert(title);  // Menu
alert(width);  // 100
alert(height); // 200
alert(item1);  // Cake
alert(item2);  // Donut
cs

 

  그런데 위 예시에서 size와 items 전용 변수는 없다는 점에 유의하자.

  전용 변수 대신 우리는 size와 items 안의 정보를 변수에 할당했다.

 

 

*출처 : ko.javascript.info/destructuring-assignment#ref-729

'Programming Language > Javascript' 카테고리의 다른 글

ES6 - 함수 표현식, 화살표 함수  (0) 2021.01.09
ES6 - Promise & Async/Await  (0) 2021.01.04
ES6 - Class(1)  (0) 2020.12.29
Rest Parameter & Spread Syntax  (0) 2020.11.06
Object Oriented Programming  (0) 2020.11.05

1. Class란?

 

  클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀로,

  객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.

 

 

2. 기본 문법

  

1
2
3
4
5
6
7
8
class MyClass {
  // 여러 메서드를 정의할 수 있음
  constructor() { ... }
  method1() { ... }
  method2() { ... }
  method3() { ... }
  ...
}
cs

 

  이렇게 클래스를 만들고, new MyClass()를 호출하면 내부에서 정의한 메서드가 들어 있는 객체가 생성된다.

  객체의 기본 상태를 설정해주는 생성자 메서드 constructor()는 new에 의해 자동으로 호출되므로,  

  특별한 절차 없이 객체를 초기화 할 수 있다.

 

  *주의 사항 : 클래스와 관련된 표기법은 객체 리터럴 표기법과 차이가 있다. 클래스에선 메서드 사이에 쉼표를 넣지 않아도 된다.

 

 

3. 상속

 

  클래스 상속을 사용하면 클래스를 다른 클래스로 확장할 수 있다.

  기존에 존재하던 기능을 토대로 새로운 기능을 만들 수 있다.

  상속은 extends 라는 키워드를 사용해 구현할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  run(speed) {
    this.speed = speed;
    alert(`${this.name} 은/는 속도 ${this.speed}로 달립니다.`);
  }
  stop() {
    this.speed = 0;
    alert(`${this.name} 이/가 멈췄습니다.`);
  }
}
 
class Rabbit extends Animal {
  hide() {
    alert(`${this.name} 이/가 숨었습니다!`);
  }
}
 
let rabbit = new Rabbit("흰 토끼");
rabbit.run(5); // 흰 토끼 은/는 속도 5로 달립니다.
rabbit.hide(); // 흰 토끼 이/가 숨었습니다!
cs

 

 

 

4. 메소드 오버라이딩, 생성자 오버라이딩

 

  개발을 하다 보면 부모 메서드 전체를 교체하지 않고, 부모 메서드를 토대로 일부 기능만 변경하고 싶을 때가 생긴다.

  부모 메서드의 기능을 확장하고 싶을 때도 있다. 이럴 때 커스텀 메서드를 만들어 작업하게 되는데,

  이미 커스텀 메서드를 만들었더라도 이 과정 전·후에 부모 메서드를 호출하고 싶을 때가 있다.

 

  키워드 super는 이럴 때 사용합니다.

 

4 - 1) 메소드 오버라이딩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Animal {
 
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
 
  run(speed) {
    this.speed = speed;
    alert(`${this.name}가 속도 ${this.speed}로 달립니다.`);
  }
 
  stop() {
    this.speed = 0;
    alert(`${this.name}가 멈췄습니다.`);
  }
 
}
 
class Rabbit extends Animal {
  hide() {
    alert(`${this.name}가 숨었습니다!`);
  }
 
  stop() {
    super.stop(); // 부모 클래스의 stop을 호출해 멈추고,
    this.hide(); // 숨습니다.
  }
}
 
let rabbit = new Rabbit("흰 토끼");
 
rabbit.run(5); // 흰 토끼가 속도 5로 달립니다.
rabbit.stop(); // 흰 토끼가 멈췄습니다. 흰 토끼가 숨었습니다!
cs

 

 

4 - 2) 생성자 오버라이딩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Animal {
 
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
 
  // ...
}
 
class Rabbit extends Animal {
 
  constructor(name, earLength) {
    super(name);
    this.earLength = earLength;
  }
 
  // ...
}
cs

 

  super(...)는 this를 사용하기 전에 반드시 호출해야 합니다.

  자바스크립트는 '상속 클래스의 생성자 함수(derived constructor)'와 그렇지 않은 생성자 함수를 구분한다.

  상속 클래스의 생성자 함수엔 특수 내부 프로퍼티인 [[ConstructorKind]]:"derived"가 이름표처럼 붙는다.

  일반 클래스의 생성자 함수와 상속 클래스의 생성자 함수 간 차이는 new와 함께 드러난다.

 

  • 일반 클래스가 new와 함께 실행되면, 빈 객체가 만들어지고 this에 이 객체를 할당합니다.
  • 반면, 상속 클래스의 생성자 함수가 실행되면, 일반 클래스에서 일어난 일이 일어나지 않습니다. 상속 클래스의 생성자 함수는 빈 객체를 만들고 this에 이 객체를 할당하는 일을 부모 클래스의 생성자가 처리해주길 기대합니다.

  이런 차이 때문에 상속 클래스의 생성자에선 super를 호출해 부모 생성자를 실행해 주어야 한다.

  그렇지 않으면 this가 될 객체가 만들어지지 않아 에러가 발생한다.

 

 

 

5. 정적 메소드와 정적 프로퍼티

 

  클래스 함수 자체에 메서드를 설정할 수도 있습니다. 이런 메서드를 정적(static) 메서드라고 부릅니다.

  정적 메서드는 클래스 안에서 static 키워드를 붙여 만들 수 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Article {
  constructor(title, date) {
    this.title = title;
    this.date = date;
  }
 
  static compare(articleA, articleB) {
    return articleA.date - articleB.date;
  }
}
 
// 사용법
let articles = [
  new Article("HTML"new Date(201911)),
  new Article("CSS"new Date(201901)),
  new Article("JavaScript"new Date(2019111))
];
 
articles.sort(Article.compare);
 
alert( articles[0].title ); // CSS
cs

 

  여기서 Article.compare는 article(글)을 비교해주는 수단으로, 글 전체를 ‘위에서’ 바라보며 비교를 수행한다. 

  Article.compare이 글 하나의 메서드가 아닌 클래스의 메서드여야 하는 이유가 여기에 있다.

 

  정적 프로퍼티도 물론 만들 수 있다.

  정적 프로퍼티는 일반 클래스 프로퍼티와 유사하게 생겼는데 앞에 static이 붙는다는 점만 다르다.

 

1
2
3
class Article {
  static publisher = "Ilya Kantor";
}
cs

 

  

 

출처 : ko.javascript.info/classes

'Programming Language > Javascript' 카테고리의 다른 글

ES6 - Promise & Async/Await  (0) 2021.01.04
ES6 - 구조 분해 할당  (0) 2020.12.31
Rest Parameter & Spread Syntax  (0) 2020.11.06
Object Oriented Programming  (0) 2020.11.05
Closure  (0) 2020.11.04

1. Rest Parameter & Spread Syntax

  1 - 1) 나머지 매개변수와 스프레드 신택스는 자바스크립트의 ES6 업데이트 후에 도입된 문법이다

  1 - 2) ... 이라는 문법을 통해 크게 Rest Parameter(나머지 매개변수), Spread(펼침) 두 가지 기능으로 활용될 수 있다.

  1 - 3) ... 은 함수에서 매개변수로 정의되면 rest parameter, 어떤 함수의 전달인자로 넘겨주면 spread syntax가 된다!

 

2. Rest Parameter

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function restParameter(a, b, ...c) {
  let sum = a + b;
  console.log(sum);
  console.log(c);
}
 
restParameter(12345);
// console -> 3
// console -> [3, 4, 5]
// rest parameter는 여분의 매개변수를
// 배열로 만들어 활용할 수 있다
// 현재 함수를 보면 전달 인자로 1, 2 는 더해져 3으로 출력되고
// 그 외의 나머지 3, 4, 5는 배열로 출력됨을 알 수 있다
// 주의할 점은 rest paremeter로 활용될 매개변수는 항상
// 매개변수의 마지막에 있어야 한다는 점이다
// 즉 a, b 보다 뒤에 존재해야 한다
// 나머지로 활용되야 하기 때문이다!
 
cs

 

 

3. Spread Syntax

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function spreadSyntax(arr) {
  let max = Math.max(...arr);
  console.log(max);
}
 
spreadSyntax([1234])
// console -> 4
// 현재는 ...이 전개 문법으로 사용되고 있다
// 이유는 ...arr이 max의 전달 인자로 사용되고 있기 때문이다
// 따라서 [1, 2, 3, 4] 라는 배열이 펼쳐져
// Math.max(1, 2, 3, 4)와 같은 현상이 일어나는 것이다
// 따라서 max 라는 변수에는 4가 할당이 된다
 
// 배열 이어붙이기
let arr1 = [1234]
let arr2 = [56]
console.log([...arr1, ...arr2]) // [1, 2, 3, 4, 5, 6]
//마찬가지로 이 경우에도 전개 문법으로서 ...이 활용되고 있다
cs

'Programming Language > Javascript' 카테고리의 다른 글

ES6 - 구조 분해 할당  (0) 2020.12.31
ES6 - Class(1)  (0) 2020.12.29
Object Oriented Programming  (0) 2020.11.05
Closure  (0) 2020.11.04
Scope  (0) 2020.11.04

1. 객체 지향 프로그래밍

  1 - 1) 객체 지향 프로그래밍이란 하나의 모델이 되는 청사진을 만들고 그 청사진을 바탕으로 한 객체를 만드는 프로그래밍 패턴이다.

  1 - 2) 이때 해당 청사진을 class라 하고 class의 객체를 instance라 한다.

  1 - 3) Instance는 new 키워드를 통해 생성될 수 있다.

  1 - 4) 자바스크립트는 원래 함수를 통해 class를 정의했으나 ES6 이후부터 자바와 같이 class 문법을 사용할 수 있게 되었다

  1 - 5) 둘의 동작 원리는 같다. 그냥 class 문법은 Syntatic sugar와 같다고 보면 된다.

  1 - 6) 클래스에서 우리가 나타내길 원하는 속성과 메소드 등을 정의할 수 있다.

 

2. ES5 vs ES6

  ES5와 ES6에서의 객체 지향 프로그래밍을 구현하는 방법을 예시 코드를 통해 살펴보자.

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//ES5
function Car(brand, name, color) {
  this.brand = brand;
  this.name = name;
  this.color = color;
}
 
Car.prototype.refuel = function() {
  //연료 공급을 구현하는 코드
  //ES5에서는 class.prototype.method의 형식을 통해
  //해당 class의 method를 정의할 수 있다.
}
 
//ES6
class Car {
  constructor(brand, name, color) {
    this.brand = brand;
    this.name = name;
    this.color = color;
  }
  refuel() {
    //연료 공급을 구현하는 코드
    //ES6에서는 해당 클래스안에 바로 method를 만들어주면 된다
  }
}
cs

 

3. this? constructor?, prototype?

  3 - 1) this : 함수가 실행될 때, 해당 scope마다 생성되는 고유한 실행 context이다.

  즉 new 키워드를 통해 instance를 생성할 때 해당 인스턴스가 바로 this인 것이다.

  3 - 2) constructor : instance가 초기화될 때 생성하는 생성자 함수

  3 - 3) prototype : 모델의 청사진을 만들 때 쓰는 원형 객체이다.

 

 

4. 예시

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Car(brand, name, color) {
  this.brand = brand;
  this.name = name;
  this.color = color;
}
 
Car.prototype.drive = function () {
  console.log(
    `${this.brand}사의 ${this.color}색을 가진
    ${this.name}이 운전을 시작합니다`
  );
};
 
let avante = new Car("hyundai""avante""black");
//avante라는 instance를 생성
avante.drive();
//hyundai사의 black색을 가진
//avante가 운전을 시작합니다
//this는 avante를 가리킴
 
cs

 

 

5. 자바스크립트에서 배열

  왜 갑자기 배열 얘기를 꺼내나 할 수 있는데 사실 우리가 사용하는 배열은 이미

  자바 스크립트 내장 객체인 Array의 instance인 것이다!

  보통 배열을 선언할 때 [] 통해 선언하여 사용하지만 이런식으로도 가능하다.

  

1
2
let arr = new Array('1''2''3')
console.log(arr) // ['1', '2', '3']
cs

  때문에 배열에서 사용할 수 있는 .push(), .indexOf()와 같은 여러가지 기능들은 사실 Array 객체에 정의된 메소드인 것이다!

'Programming Language > Javascript' 카테고리의 다른 글

ES6 - Class(1)  (0) 2020.12.29
Rest Parameter & Spread Syntax  (0) 2020.11.06
Closure  (0) 2020.11.04
Scope  (0) 2020.11.04
2020/09/30 - JS - 반복문  (0) 2020.09.30

1. 클로저

  1 - 1) 클로저란 외부 함수의 변수에 접근할 수 있는 내부 함수 또는 이러한 작동 원리를 일컫는 용어이다.

  1 - 2) 클로저 함수는 자기 자신의 스코프, 외부 함수 스코프, 전역 스코프 총 3가지의 스코프에 접근이 가능하다

 

  예시를 통해 클로저에 대해 구체적으로 알아보자!

  

1
2
3
4
5
6
7
8
9
10
11
12
13
//closure
function outerFn(a) {
  return function innerFn(b) {
    return a + b;
  }
}
 
let sum = outerFn(3)
console.log(sum(2)) 
// 5
// 위와 같은 예가 클로저이다
// innerFn의 a는 outerFn의 지역 변수로서
// innerFn에서 접근해 사용되었기 때문이다
cs

 

2. 유용한 클로저 예제

  2 - 1) 커링 : 함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법.

  

1
2
3
4
5
6
7
8
9
10
11
12
13
function adder(x) {
  return function (y) {
    console.log(x + y);
  };
}
 
adder(2)(5); //7
 
let num = adder(100);
// x의 값을 고정시켜서 사용할 수도 있다!
num(5); // 105
num(10); // 110
 
cs

 

 

  2 - 2) 클로저 모듈 패턴 : 변수를 스코프 안쪽에 가두어 함수 밖으로 노출시키지 않기 위한 방법.

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function makeCounter() {
  let privateCnt = 0;
  return {
    increment: function () {
      privateCnt++;
    },
    decrement: function () {
      privateCnt--;
    },
    getCnt: function () {
      console.log(privateCnt);
    }
  };
}
 
let cnt1 = makeCounter();
 
cnt1.increment();
cnt1.increment();
cnt1.increment();
cnt1.decrement();
cnt1.getCnt(); // 2
 
let cnt2 = makeCounter();
 
cnt2.decrement();
cnt2.increment();
cnt2.decrement();
cnt2.decrement();
cnt2.getCnt(); // -2
 
cs

'Programming Language > Javascript' 카테고리의 다른 글

Rest Parameter & Spread Syntax  (0) 2020.11.06
Object Oriented Programming  (0) 2020.11.05
Scope  (0) 2020.11.04
2020/09/30 - JS - 반복문  (0) 2020.09.30
2020/09/18 - JS - 문자열과 관련 메소드  (0) 2020.09.18

+ Recent posts