[JS] #5 For-of, getter, setter

For-of

  • Syntax: for(variable of iterable){ }
  • 이터러블 오브젝트를 반복합니다.
const list = [1, 2, 3];
for(let k = 0; k < list.length; k++) {
  console.log(list[k]);
};
for(let value of list) {
  console.log(value);
};
// 1
// 2
// 3
// 1
// 2
// 3
  • iterable
    list 자리에 이터러블 오브젝트를 작성
    표현식을 작성하면 평가 결과를 사용합니다.

  • variable
    변수 이름 작성
    이터러블 오브젝트를 반복할 때마다 variable에 값이 할당됩니다.

  • 배열
    배열을 반복하며 엘리먼트를 하나씩 전개합니다.

    for(let value of [1,2,3]) {
      console.log(value);
    }
    // 1
    // 2
    // 3
  • String
    문자열을 반복하면서 문자를 하나씩 전개합니다.

    for(let value of "ABC") {
      console.log(value);
    }
    // A
    // B
    // C
  • NodeList
    NodeList를 반복하며 엘리먼트를 하나씩 전개

    <ul>
      <li class="show">첫 번째</li>
      <li class="show">두 번째</li>
      <li class="show">세 번째</li>
    </ul>
    const nodes = document.querySelectorAll(".show");
    for(let node of nodes) {
      console.log(node.textContent);
    };
    // 첫 번째
    // 두 번째
    // 세 번째

for-in, for-of 차이

  • for-of
    • 이터러블 오브젝트가 대상
    • Object는 전개되지 않습니다.
    • prototype의 프로퍼티도 전개되지 않습니다.
  • for-in
    • 열거 가능한 프로퍼티가 대상입니다.
    • {key: value}의 오브젝트 리터럴 형태는 디폴트가 enumerable: true
    • Object.defineProperty()는 디폴트가 enumerable: false
      const obj = { };
      Object.defineProperties(obj, {
        sports: {
          enumerable: false, value: "스포츠"
        },
        book: {
          enumerable: true, value: "책"
        },
      });
      for(let item in obj) {
      	console.log(item + ": " + obj[item]);
      };
      // book: 책

for-of, Object

  • Object는 이터러블 오브젝트가 아니기에 for-of 사용이 불가능합니다.
  • 하지만, Object.keys()로 프로퍼티 이름을 배열로 만든 뒤 만든 배열을 for-of로 전개하면 사용가능합니다.
    const sports ={
      soccer: "축구",
      baseball: "야구"
    };
    const keyList = Object.keys(sports);
    for(let key of keyList){
      console.log(key + ": " + sports[key]);
    };
    // soccer: "축구"
    // baseball: "야구"

연산자, 기타

Trailing commas

const obj = {
  book: 100, 
  point: 200,
};
const list = [100, 200,];

Object 끝에 콤마를 사용할 수 있습니다. ES5에서는 블록을 닫는 마지막 중괄호 앞에 콤마를 작성하면 에러가 발생했는데, ES6부터는 Object뿐 아니라 배열 끝에도 콤마 사용이 가능합니다.

거듭 제곱

console.log(2 ** 3);  // 8
console.log(3 ** 2);  // 9
console.log(2 ** 3 ** 2);  // 512
console.log(2 ** (3 ** 2));  // 512
console.log((2 ** 3) ** 2);  // 64

⇒ 2**3**2는 먼저 3의 2승을 구하게됩니다. 그렇기에 2의 9승이 되어 512가 됩니다.

  • 좌결합성
    • 왼쪽에서 오른쪽으로 계산합니다.
    • 1 + 2 + 3은 (1 + 2) + 3으로 계산합니다.
  • 우결합성
    • 오른쪽에서 왼쪽으로 계산합니다.
    • A ** B ** C 에서 A ** (B ** C)로 계산합니다.
    • 소괄호를 통해 우선 평가 대상을 바꿀 수 있습니다.
    • (2 ** 3) ** 2 에서는 소괄호부터 평가를 하기때문에 9의 2승이 됩니다.

try- catch

const sports = "스포츠";
try {
  sports = "축구";
} catch(error) {
  console.log("(error) 작성")
};
try {
  sports = "축구";
} catch {
  console.log("(error) 생략")
};
// (error) 작성
// (error) 생략
  • try-catch의 catch(error)에서 catch처럼 (error)를 생략 가능합니다.
  • (error)에서 메세지를 받아 사용하지 않을 때 편리합니다.
  • 타이핑 실수를 방지할 수 있습니다.

함수 작성 형태

Object에 함수를 작성할 때 function 키워드를 작성하지 않습니다.

const sports = {
  point: 100,
  // ES5 형태
  getValue: function(){
    return this.point;
  },
  // ES6 형태
  getPoint(){
    return this.point;
  }
};
console.log(sports.getPoint());
// 100
  • Object에 함수를 작성하는 이유
    • 프로퍼티 함수에서 this로 Object 전체 참조
    • new연산자로 인스턴스를 생성하지 않음
      (메소드가 아닌 함수로 접근)
    • Object 전체가 하나의 묶음이기에 접근성/가독성이 좋음
    • sports에 시맨틱을 부여할 수 있으며 다른 오브젝트 이름과 프로퍼티 이름이 충돌되지 않습니다.

getter

getter로 선언된 함수를 자동으로 호출합니다.
getter는 값을 반환하는 시맨틱을 가지고 있기에 getter 함수에서 값을 반환해야 합니다.

  1. ES5형태
    ⇒ book.title을 실행하면 title 프로퍼티에서 get속성의 존재를 체크합니다. 이때 프로퍼티가 있으면 get()함수를 호출합니다.
    여기서 book.title.get()으로 호출하면 에러가 발생합니다. 이는 ES5의 Descriptor를 참고하시면 됩니다.

    var book = {};
    Object.defineProperty(book, "title", {
      get: function(){
        return "책";
      }
    });
    console.log(book.title); 
    // 책
  2. ES6형태
    ⇒ get getPoint(){ }와 같이 getPoint() 앞에 get을 작성하면 getter로 선언됩니다. 그래서 getPoint()함수가 자동으로 호출됩니다.

    const book = {
      point: 100,
      get getPoint(){
        return this.point;
      }
    };
    console.log(book.getPoint);
  • 장점
    ES5처럼 프로퍼티의 속성 구조가 아닙니다.
    작성이 편리하며 다수의 getter 사용도 가능합니다
    const book = {
      point: 100,
      get getPoint(){
        return "포인트";
      },
      get getTitle(){
        return "제목";
      }
    };
    console.log(book.getPoint);
    console.log(book.getTitle);
    // 포인트
    // 책

setter

프로퍼티에 값을 할당하면 setter로 선언된 함수가 자동으로 호출됩니다. 이는 setter가 값을 설정하는 시맨틱을 가지고 있기에 setter 함수에서 값을 설정해줘야 합니다.

  1. ES5형태
    ⇒ book.change = "자바스크립트"를 실행하면 change프로퍼티에서 set 속성의 존재 여부를 체크합니다. 있을 경우 set()함수를 호출하고 "자바스크립트"를 파라미터 값으로 넘겨줍니다.

    var book = {title: "HTML"};
    Object.defineProperty(book, "change", {
      set: function(param) {
        this.title = param;
      }
    });
    book.change = "자바스크립트";
    console.log(book);
    // {title: 자바스크립트}
  2. ES6형태
    ⇒ setPoint()앞에 set을 작성하면 setter로 선언됩니다.
    ⇒ book.setPoint = 200;
    setPoint에 값을 할당하면 setPoint()가 자동으로 호출되어 파라미터값으로 200을 넘겨줍니다.

    const book = {
      point: 100,
      set setPoint(param) {
        this.point = param;
      }
    };
    book.setPoint = 200;
    console.log(book.point);
    // 200
  3. 변수값을 함수 이름으로 사용
    ⇒ name 변수값인 "setPoint"가 함수 이름으로 사용됩니다.
    getter 역시 같은 방법으로 사용이 가능합니다.

    const name = "setPoint";
    const book = {
      point: 100,
      set [name](param){
        this.point = param;
      }
    };
    book[name] = 200;
    console.log(book.point);
    // 200
  • setter 삭제
    ⇒ delete 연산자로 setter를 삭제할 수 있습니다.
    const name = "setPoint";
    const book = {
      point: 100,
      set [name](param){
        this.point = param;
      }
    };
    delete book[name];
    console.log(book[name]);
    // undefined

좋은 웹페이지 즐겨찾기