수업

객체 프로퍼티 플래그


객체 프로퍼티가 갖는 세가지 플래그(flag)
writable : true일 때만 값을 수정할 수 있다.
enumerable: true일 때만 반복문을 사용해 나열할 수 있다.
configurable: true일 때만 프로퍼티 삭제나 플래그 수정이 가능하다.

일반적인 방식으로 프로퍼티를 만들었을 때는 true값이 기본이다.

Object.getOwnPropertyDescriptor(객체, 프로퍼티)를 입력하면,
프로퍼티에 대한 정보가 나온다.


let user = {
    name: "John"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

descriptor
-> {value: 'John', writable: true, enumerable: true, configurable: true}
	configurable: true
	enumerable: true
	value: "John"
	writable: true
[[Prototype]]: Object




플래그를 false로 만들어 수정하지 못하게 할 수 있다.

configurable:false는 몇몇 내장 객체나 프로퍼티에 기본으로 설정되어 있다.
그 중 하나가, Math:PI
수정과 삭제가 불가능하다.
한 번 configurable:false를 쓰면 다시 true로 돌아올 수 없다.



접근자 프로퍼티( getter, setter )

간단하게 말하면, getterobject를 어떤 값으로 불러오기(획득하기) 위해 사용하고,
setter는 그걸 설정하기 위해 사용한다.

let user = {
  name: "Hyemi",
  surname: "Jo",

  get fullName() {
    return `${this.name} ${this.surname}`;
  }
};

document.write(user.fullName); // Hyemi Jo

fullName을 구현하기 위해 get을 사용했다. 다만, getter 메서드만 있기 때문에 값을 할당 하지는 못한다.
user.fullName = "Gildong Hong"은 에러가 난다.
이럴 때 사용하는게, setter 메서드이다.

let user = {
  name: "Hyemi",
  surname: "Jo",

  get fullName() {
    return `${this.name} ${this.surname}`;
  }
  set fullName() {
  	[this.name, this.surname] = value.split(" ");
  }
};

user.fullName = "Gildong Hong"

이라고 하면, 여기에서 userfullNameGildong Hong이 되고,
user.nameGildong
user.surnameHong이 된다.


getter로 불러오고 setter로 설정(조작) 해주기



프로토타입( prototype )


prototype: 유전자(상속받은 객체)
__proto__는 [[Prototype]]에 접근하기 위한 방법
__proto__는 비표준으로 시작했으나 지금은 표준의 부록에 실렸다.

프로토타입 상속: object에서 프로퍼티가 없으면, 프로토타입에서 프로퍼티를 찾는다.

let animal = {
  eats: true
};
let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal; // (*)

// 프로퍼티 eats과 jumps를 rabbit에서도 사용할 수 있게 되었습니다.
alert( rabbit.eats ); // true (**)
alert( rabbit.jumps ); // true

여기에서 rabbit의 프로토타입은 animal이다.
rabbit에는 eats가 없지만, animal에게서 상속받았기 때문에, rabbit.eatstrue이다.



클래스


  • 함수의 한 종류이다.
  • 특수 내부 프로퍼티인 [[FunctionKind]]:"classConstructor"가 생긴다.
  • 열거할 수 없다.(non-enumerable)
  • 항상 use strict 모드
  • 단순한 편의문법(syntactic sugar)는 아니다. (+@ 느낌?)

클래스의 장점: 기존의 함수처럼도 되고, #을 붙여서 접근 못하게도 가능하다. - 견고하게 js를 만들 수 있게 해준다.


class User {

  constructor(name) {
    this.name = name;
  }

  sayHi() {
    alert(this.name);
  }

}

// 사용법:
let user = new User("John");
user.sayHi();

///
class User {
  constructor(name) { this.name = name; }
  sayHi() { alert(this.name); }
}

// 클래스는 함수입니다.
alert(typeof User); // function

// 정확히는 생성자 메서드와 동일합니다.
alert(User === User.prototype.constructor); // true

// 클래스 내부에서 정의한 메서드는 User.prototype에 저장됩니다.
alert(User.prototype.sayHi); // alert(this.name);

// 현재 프로토타입에는 메서드가 두 개입니다.
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

폴리필: 구 브라우저를 지원하기 위해 문법을 채워넣는 것. 그 중 하나가 바벨

클래스 : 객체를 만들 때 수 많은 지원을 하는 대신 많은 제한을 거는 문법
프로토타입 : 제한을 많이 하지 않지만, 대신 지원도 별로 하지 않는 문법


메서드 오버라이딩

상속받은 메서드가 아니라, 자체적으로 정의해서, 자체 메서드를 사용하는 것이다.
나한테 가장 가까운, 메서드를 사용한다.
덮어쓴거나 없애는게 아니다.

자바스크립트에는 오버로딩이 없다


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(); // 흰 토끼가 멈췄습니다. 흰 토끼가 숨었습니다!

protected, private 프로퍼티

protected프로퍼티: 프로퍼티 명 앞에 '_'(언더바)를 붙여서 사용한다.
강제는 아니지만 수정하지 말라는 암묵적인 약속이다.

class CoffeeMachine {
  _waterAmount = 0;

  set waterAmount(value) {
    if (value < 0) throw new Error("물의 양은 음수가 될 수 없습니다.");
    this._waterAmount = value;
  }

  get waterAmount() {
    return this._waterAmount;
  }

  constructor(power) {
    this._power = power;
  }

}

// 커피 머신 생성
let coffeeMachine = new CoffeeMachine(100);

// 물 추가
coffeeMachine.waterAmount = -10; // Error: 물의 양은 음수가 될 수 없습니다.

private프로퍼티: 프로퍼티 명 앞에 '#'을 붙여서 사용한다.
클래스 안에서만 접근이 가능하다. 외부나, 자손이 접근 불가능하다. 강제 된다.

class CoffeeMachine {
  #waterLimit = 200;

  #checkWater(value) {
    if (value < 0) throw new Error("물의 양은 음수가 될 수 없습니다.");
    if (value > this.#waterLimit) throw new Error("물이 용량을 초과합니다.");
  }

}

let coffeeMachine = new CoffeeMachine();

// 클래스 외부에서 private에 접근할 수 없음
coffeeMachine.#checkWater(); // Error
coffeeMachine.#waterLimit = 1000; // Error

생각

손코딩을 여태까지는 그냥 이면지에 쭉 적어보는 방식으로 했는데, 오늘 수업시간에 했던 것처럼 이 코드가 어떤걸 의미하고 있는건지 생각하면서 쓰고, 잘 모르겠는 부분을 다른 색으로 주석을 달아가면서 하니 정말 더 이해가 쉬웠다. 앞으로 이해가 잘 안 되는 것은 꼭 손코딩해봐야겠다.


느낀점

잘한점

  • 손코딩 수업 때 못한 부분도 끝까지 하고, 복습까지 한 점. 적어도 오늘 배운 부분은 다 이해하고 가려고 열심히 수업 끝나고도 손코딩을 해봤다. 주석을 쓰면서 찾아보니까 더 기억에 잘 남는 것 같다.
  • 일찍 자고 일찍 일어난 점. 12시 전에 자는건 실패했지만, 12시 반 전에는 잤다! 넉넉하게 자니까 확실히 집중이 다른 때보다 잘 된 것 같다!

계획

  • 손코딩!!! 그날 이해 안 간 것은 꼭 손코딩 해보기
  • 수면시간 6시간 이상, 운동 주 3회 이상!


수업, 기록 참고: 모던 JavaScript 튜토리얼- https://ko.javascript.info/

profile
2021.11~

0개의 댓글