ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ES6] ES6 문법 정리 10가지
    Front-End/JavaScript 2021. 10. 25. 17:36

     

    ES6가 포함하는 10가지 기능에 대해서 공부해보았다.

    • const and let
    • Arrow functions(화살표 함수)
    • Template Literals(템플릿 리터럴)
    • Default parameters(기본 매개 변수)
    • Array and object destructing(배열 및 객체 비구조화)
    • Import and export(가져오기 및 내보내기)
    • Promises(프로미스)
    • Rest parameter (나머지 매개 변수)
    • Spread operator(확산 연산자)
    • Classes(클래스)

     

    1. const, let

    const : 사용되면 변수 재할당 불가. 객체와 함께 사용할 때를 제외하고는 변경 불가능

    let : 새로운 값을 가질 수도 있고 재할당도 가능.

    둘 다 블록 범위.

     

    근데 이게 무슨 말이지? 객체와 함께 사용할 때는 재할당 할 수 있다는 말인가?

    라는 의문이 들었는데 더 찾아보니까 이런 뜻인 것 같았다.

    const user = { name: 'Lee' };
    
    // const 변수는 재할당이 금지
    // user = {}; // TypeError: Assignment to constant variable.
    
    // 객체의 내용은 변경가능
    user.name = 'Kim';
    
    console.log(user); // { name: 'Kim' }

    const는 선택자를 대상으로 하는 데 매우 유용하다.

    예를 들어 이벤트를 실행하는 단일 단추가 있거나 JavaScript에서 HTML 요소를 선택하려면 var 대신 const를 사용하는 것을 권장한다. 이것은 var가 '호이스팅(hoisting)'이기 때문이다. 변수를 재할당하지 않으려면 항상 상수를 사용하는 것이 좋다.

    hoisting은 또 뭐지?

    JavaScript에서 호이스팅 (hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다. 
    var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다. 반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다.
    let과 const로 선언한 변수도 호이스팅 대상이지만, var와 달리 호이스팅 시 undefined로 변수를 초기화하지는 않습니다. 따라서 변수의 초기화를 수행하기 전에 읽는 코드가 먼저 나타나면 예외가 발생합니다.

     

    2. Arrow functions(화살표 함수)

    기존 방식 (ES5)

    // ES5
    function myFunc(name) {
    	return '안녕' + name;
    }
    
    console.log(myFunc('영희'));
    
    // 출력 => 안녕 영희

    ES6 화살표 함수

    // ES6 화살표 함수
    const myFunc = (name) => {
    	return `안녕 ${name}`;
    }
    console.log(myFunc('영희')); // 출력 => 안녕 영희
    
    // 또는 화살표를 사용하거나 'return' 키워드를 사용하지 않아도 됩니다
    const myFunc = (name) => `안녕 ${name}`;
    console.log(myFunc('영희')); // 출력 => 안녕 영희

    또한, 화살표 함수를 map filter, reduce 등 내장 함수와 함께 사용할 수 있습니다.

     

    Map

    배열 각 요소에 대하여 주어진 함수를 수행한 결과를 모아 새로운 배열을 반환하는 메서드
    3개의 매개변수를 가지고 있음.
    - value : 현재요소
    - index : 요소의 인덱스, 필수 입력 아님 
    - array : map()을 호출한 원본 배열, 필수 입력 아님

    const numbers = [1, 2, 3, 4];
    const doubled = numbers.map(item => item * 2);
    console.log(doubled); // [2, 4, 6, 8]

    Filter

    배열 각 요소에 대하여 주어진 함수 결괏값이 true인 요소를 모아 새로운 배열을 반환하는 메서드
    3개의 매개변수를 가지고 있음.
    - value : 현재요소
    - index : 요소의 인덱스, 필수 입력 아님 
    - array : 원본 배열, 필수 입력 아님

    const numbers = [1, 2, 3, 4];
    const evens = numbers.filter(item => item % 2 === 0);
    console.log(evens); // [2, 4]

    Reduce

    배열 각 요소에 대하여 reducer 함수를 실행하고, 하나의 결괏값만 반환
    4개의 매개변수를 가지고 있음
    - accumulator : 누산기 (reduce 함수를 수행하면서 생기는 값을 임시적으로 보관하는 형태), 리턴한 값을 저장하는 변수. 초기값을 지정한 경우에는 초기값부터 시작. (예제에서는 초기값이 0) 
    - currentValue : 현재 요소
    - currentIndex : 요소의 인덱스, 필수 입력 아님
    - array : 원본 배열, 필수입력 아님

    const numbers = [1, 2, 3, 4];
    const sum = numbers.reduce(function (result, item) {
      return result + item;
    }, 0);
    console.log(sum); // 10

     

    3. Template Literals(템플릿 리터럴)

    문자열을 연결하기 위해 더하기(+) 연산자를 사용할 필요는 없으며, 백틱(`)을 사용하여 문자열 내에서 변수를 사용할 수도 있습니다.

    // ES5
    function myFunc1() {
    	return '안녕' + name + '너의 나이는' + age + '살 이다!'; 
    }
    
    // ES6
    const myFunc = (name, age) => {
    	return `안녕 ${name}, 너의 나이는 ${age}살 이다!`; 
    };

     

    4. Default parameters(기본 매개 변수)

    const myFunc = (name, age = 22) => {
    	return `안녕 ${name} 너의 나이는 ${age}살 이니?`; 
    };
    
    console.log(myFunc('영희'));
    // 출력 => 안녕 영희 너의 나이는 22살 이니?

    이런 건데 궁금증이 생겼다. 

    const myFunc = (name = '철수', age) => {
    	return `안녕 ${name} 너의 나이는 ${age}살 이니?`; 
    };
    
    console.log(myFunc(25));
    // 출력 => 안녕 25 너의 나이는 undefined살 이니?

    매개변수 갯수가 다르면 기본 매개 변수를 우선으로 출력하고 기본 매개 변수가 없는 파라메터에 값을 넣어줄 줄 알았더니 그건 아니었다. 저걸 동작시키려면 아래와 같이 해야 한다.

    const myFunc = (name = '철수', age) => {
    	return `안녕 ${name} 너의 나이는 ${age}살 이니?`; 
    };
    
    console.log(myFunc(undefined,25));

     

    5. Array and object destructing(배열 및 객체 비구조화)

    const contacts = {
    	famillyName: '이',
    	name: '영희',
    	age: 22
    };
    
    let { famillyName, name: ontherName, age } = contacts;
    
    console.log(famillyName);
    console.log(ontherName);
    console.log(age);

    이런 걸 비구조화라고 한다. 

    객체의 요소를 새로운 변수에 할당할 때 한꺼번에 할당할 수 있는 장점이 있고,

    요소와 변수의 이름이 다르면 undefined가 뜨기 때문에 콜론으로 명명을 해줘야 한다.

    배열은 중괄호를 대괄호로 바꾼 형태이다.

    const arr = ['광희', '지수', '영철', 20];
    
    let [value1, value2, value3] = arr;
    
    console.log(value1);
    console.log(value2);
    console.log(value3);

     

    6. Import and export(가져오기 및 내보내기)

    require나 import 키워드를 통해 외부 라이브러리를 불러오는 코드를 자주 보게 된다. require는 NodeJS에서 사용되고 있는 CommonJS 키워드이고, import는 ES6(ES2015)에서 새롭게 도입된 키워드.

    //CommonJS
    const moment = require("moment");
    
    //ES6
    import moment from "moment";

    그런데 CommonJS와 ES5는 다른 것인가? 대충 훑어보니 다른 것 같긴 한데, 이것에 대해서는 다른 장에서 알아보도록 하겠다.

     

    CommonJS 의 내보내기 : exports 변수의 속성으로 내보낼 함수들을 세팅한다.

    const func1 = function (param) {
      return param;
    };
    
    function func2() {
      return "hello world!";
    }
    
    exports.func1 = func1; // 내보내기 1
    exports.func2 = func2; // 내보내기 2

    CommonJS의 불러오기 : 위에서 내보낸 여러 개의 객체는 require 키워드를 통해 한 번에 불러와 변수에 할당할 수 있으면, 그 변수를 통해서 내보낸 객체에 접근할 수 있다.

    const currency = require("./resource");
    
    console.log(currency.func1(50));
    console.log(currency.func2());

     

    ES6의 내보내기

    // 내보내기 1
    export function func1(param) {
      return param;
    }
    
    // 내보내기 2
    const func2 = function () {
      return "hello!";
    };
    export { func2 };

    혹은 이렇게도 된다

    export default {
      func1(param) {
        return param;
      },
    
      func2: function () {
        return "hello!";
      },
    };

    또는 이렇게도 된다. 변수를 할당해서 내보내기를 하는 건데, 불러내는 쪽에서 변수명을 꼭 사용할 필요는 없다.

    const obj = {
      func1(param) {
        return param;
      },
    };
    
    obj.func2 = function () {
      return "hello!";
    };
    
    export default obj;

     

    ES6의 불러오기

    // Destructuring
    import { func1 } from "./resource-functions";
    console.log(func1(50));
    
    // Alias
    import * as resource from "./resource-functions";
    console.log(resource.func2());

     

    7. Promises(프로미스)

    비동기 코드를 쓰는 방법. 예를 들어 API에서 데이터를 가져오거나 실행하는데 시간이 걸리는 함수를 가지고 있을 때 사용할 수 있다고 한다.

    싱글쓰레드인 자바스크립트에서 비동기 처리를 위해서 콜백(callback)을 사용해왔다.
    덕분에 비동기 처리를 온전히 해낼 수 있었지만 이런 콜백이 사용되는 경우가 많아지면서 단점이 드러났다.
    그 단점은 비동기 처리를 순차적으로 실행할 필요가 있는 경우에 비동기 처리를 중첩시켜서 표현하므로 에러, 예외처리가 어렵다는 것과 중첩으로 인한 복잡도가 증가하는 것이다.
    크게 이 두 가지의 단점을 해결하기위해 프로미스가 예전부터 라이브러리로 생겨났고, 이것을 ES6에서는 언어적 차원에서 지원하게 되었다.

    const param = true;
    const promise1 = new Promise(function(resolve,reject){
        if(param){
          resolve("바보");
        }
        else{
          reject("아닌데");
        }
    });
    const promise2 = new Promise(function(resolve,reject){
        if(param){
          resolve("바보2");
        }
        else{
          reject("아닌데2");
        }
    });
    Promise.all([promise1,promise2]).then(function(values){
        console.log("1,2,3 모두완료",values);
    });

    여러개의 프로미스를 사용하는 건 처음 봐서 가져와봤다. 

     

    8. Rest parameter(나머지 매개 변수)

    함수의 마지막 매개변수 앞에 "..."를 붙이면 (사용자가 제공한) 모든 후속 매개변수를 배열에 넣도록 지정한다.

    마지막 매개변수만 나머지 매개변수로 설정할 수 있다.

    function myFun(a, b, ...manyMoreArgs) {
      console.log("a", a);
      console.log("b", b);
      console.log("manyMoreArgs", manyMoreArgs);
    }
    
    myFun("one", "two", "three", "four", "five", "six");
    
    // 콘솔 출력:
    // a, one
    // b, two
    // manyMoreArgs, [three, four, five, six]

     

    9. Spread operator(확산 연산자)

    Spread operator는 Rest parameter와 구문이 동일하지만 Spread operator는 인수뿐만 아니라 배열 자체를 가진다.
    for 반복문이나 다른 메서드를 사용하는 대신 Spread operator를 사용하여 배열의 값을 가져올 수 있다.

    const arr = ['영희', 20, '열성적인 자바스크립트', '안녕', '지수', '어떻게 지내니?'];
    
    const Func = (...anArray) => {
    	return anArray;
    };
    console.log(Func(arr));
    // 출력 => ["영희", 20, "열성적인 자바스크립트", "안녕", "지수", "어떻게 지내니?"]

    이건 뭐 당연하고 아래 예는 꽤 신기하다.

    function myFunction(v, w, x, y, z) { }
    var args = [0, 1];
    myFunction(-1, ...args, 2, ...[3]);
    // 이게 된다
    
    var dateFields = [1970, 0, 1];  // 1 Jan 1970
    var d = new Date(...dateFields);
    //이것도 됨

     

    10. Classes(클래스)

    객체지향 프로그램의 핵심이라고 할 수 있다. 코드를 안전하게 캡슐화 할 수 있다.

    함수 선언과 클래스 선언의 중요한 차이점은 함수 선언의 경우 호이스팅이 일어나지만, 클래스 선언은 그렇지 않다는 것. 따라서 클래스를 사용하기 위해서는 클래스를 먼저 선언해야 한다.

     

    class 선언 방법

    class Rectangle {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
    }

    class 표현식 방법

    Class 표현식은 이름을 가질 수도 있고, 갖지 않을 수도 있다. 이름을 가진 class 표현식의 이름은 클래스 body의 local scope에 한해 유효하다. (name 속성을 통해 접근한다). 내게는 낯선 표기법이다. 실무에서 자주 사용할까...?

    // unnamed
    let Rectangle = class {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
    };
    console.log(Rectangle.name);
    // 출력: "Rectangle"
    
    // named
    let Rectangle = class Rectangle2 {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
    };
    console.log(Rectangle.name);
    // 출력: "Rectangle2"

    getter를 지정해주는 방식도 신선했다.

    class Rectangle {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
      // Getter
      get area() {
        return this.calcArea();
      }
      // 메서드
      calcArea() {
        return this.height * this.width;
      }
    }
    
    const square = new Rectangle(10, 10);
    
    console.log(square.area); // 100

    상속(extends) 도 가능하다

    class myClass {
    	constructor(name, age) {
    		this.name = name;
    		this.age = age;
    	}
    
    	sayHello() {
    		console.log(`안녕 ${this.name} 너의 나이는 ${this.age}살이다`);
    	}
    }
    
    // myClass 메서드 및 속성 상속
    class UserProfile extends myClass {
    	userName() {
    		console.log(this.name);
    	}
    }
    
    const profile = new UserProfile('영희', 22);
    
    profile.sayHello(); // 안녕 영희 너의 나이는 22살이다.
    profile.userName(); // 영희

    참고

Designed by Tistory.