Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[24/08/22-28] 안내 및 질문 모음집 #19

Open
minjeongss opened this issue Aug 22, 2024 · 5 comments
Open

[24/08/22-28] 안내 및 질문 모음집 #19

minjeongss opened this issue Aug 22, 2024 · 5 comments

Comments

@minjeongss
Copy link
Collaborator

minjeongss commented Aug 22, 2024

📚 분량

15장-19장

🎤 발표자

김주영

질문

15장

  • p.213, TDZ의 개념이 확실히 이해 가지 않아 더 자세히 알고싶음(+예시) (김주영)

18장

  • __proto__와 prototype이 사용되는 예시는 무엇이 있는가? (김민정)
  • arguments 객체는 가변 인자 함수를 구현할 때 유용한데, 인수의 개수를 지정해야 줘야하는 타입스크립트에서는 필요가 없는지? (김민석)

19장

  • ES6의 클래스 문법과 프로토타입 기반 상속의 차이점은? (김민석)
  • 프로토타입 기반 상속과 클래스 기반 상속의 장단점을 비교 (JS에서 다중 상속을 구현하는 방법과 그 한계점) (김주영)
  • 프로토타입 - 실 개발에서 프로토타입을 교체하는 경우? (조천산)
@shlee9999
Copy link
Collaborator

shlee9999 commented Aug 28, 2024

15장

  • p.213, TDZ의 개념이 확실히 이해 가지 않아 더 자세히 알고싶음(+예시) (김주영)

    • TDZ(Temporal Dead Zone)는 선언문 이전에 해당 변수에 접근할 수 없는 영역을 의미합니다.
    // a를 선언했지만 선언문 이전엔 a를 참조할 수 없습니다. 
    // 이 선언문 상단은 모두 식별자 a의 TDZ입니다.
    let a = 1;

18장

  • __proto__와 prototype이 사용되는 예시는 무엇이 있는가? (김민정)

    • proto

      __proto__의 경우, 내부슬롯 [[Prototype]]에 대한 접근자 프로퍼티입니다. [[Prototype]]을 setter 함수 (__proto__나 Object.setPrototypeOf()) 메서드를 사용해 바꾸는 것은 공식문서에서도 권장되지는 않더라구요, 성능 저하를 일으킨다고 명시되어 있습니다. 대신 [Object.create()](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/create)를 사용하여 원하는 [[Prototype]]으로 새 객체를 만드는 방법이 권장됩니다. 고로 저희가 setter 함수를 통해 바꿀 일은 거의 없지만 prototype 체인을 거슬러 올라갈 때 이 [[Prototype]]가 참조하는 곳으로 거슬러 올라가는 거라는 개념을 알고 계셔야 할 것 같습니다. 책에도 나와있지만, 접근자 프로퍼티를 사용하는 이유는 프로토타입 체인이 단방향 링크드 리스트 형태인데, 무한 루프를 돌게 하지 않기 위함이에요. 아마 그 setter함수의 내부 로직에 이 무한루프를 검사하는 로직이 포함되어 있을 것 같습니다. MDN에서 찾아보려고 했는데 사용 syntax만 있고 딥한 로직까지는 안나와 있더라구요.

      공식문서에서

      function Person(name) {
        this.name = name;
      }
      const me = new Person();
      console.log(Person.prototype === me.__proto__); // true

      image

    • prototype

      주로 생성자 함수를 통해 객체를 생성할 때 인스턴스들이 모두 가지고 있어야 할 프로퍼티나 메서드가 있다면 prototype에 등록해줍니다. (프로퍼티 키는 같지만, 값은 다른 경우입니다. 모두 같은 값을 가진다면 prototype이 아닌 정적 프로퍼티, 정적 메서드로 함수 객체에 직접 등록하는 게 인스턴스 생성 없이도 사용할 수 있으므로 좋습니다.) class와 비교해서 생각해보시면 어렵지 않습니다.

      //생성자 함수와 prototype을 이용한 상속
      function Animal(name) {
        this.name = name; // name 프로퍼티를 등록합니다.
      }
      
      Animal.prototype.walk = function () {
        console.log(`${this.name} is walking!`); // Animal.prototype에 walk 메서드를 등록합니다. this(미래에 생성할 인스턴스)에 따라 달라집니다.
      };
      
      function Dog(name) {
        Animal.call(this, name); // 인스턴스에 name 프로퍼티 등록. prototype과 관련 없음
      }
      Dog.prototype.__proto__ = Animal.prototype; // Dog의 [[Prototype]]에 Animal.prototype을 넣어줍니다. 프로토타입 체인 형성
      //* 앞서 __proto__를 질문하셔서 이렇게 했지만, 아래 주석처럼 해주는 것이 더 권장되는 방식입니다.
      // Dog.prototype = Object.create(Animal.prototype);
      // Dog.prototype.constructor = Dog; // constructor 프로퍼티를 명시적으로 설정해 주는 것이 좋습니다.
      
      Dog.prototype.bark = function () {
        console.log(`${this.name} is barking!`); // Dog.prototype에 bark 메서드를 등록합니다. this(미래에 생성할 인스턴스)에 따라 달라집니다.
      };
      const tomas = new Dog('tomas');
      
      tomas.bark(); // tomas is barking!
      tomas.walk(); // tomas is walking!
      class Animal {
        constructor(name) {
          this.name = name; // name 프로퍼티를 등록합니다.
        }
        walk() {
          console.log(`${this.name} is walking!`); // Animal.prototype에 walk 메서드를 등록합니다. this(미래에 생성할 인스턴스)에 따라 달라집니다.
        }
      }
      
      class Dog extends Animal { // Dog.prototype의 [[Prototype]]에 Animal.prototype을 넣어줍니다. 프로토타입 체인 형성
        constructor(name) {
          super(name); // 인스턴스에 name 프로퍼티 등록. prototype과 관련 없음
        }
        bark() {
          console.log(`${this.name} is barking!`); // Dog.prototype에 bark 메서드를 등록합니다. this(미래에 생성할 인스턴스)에 따라 달라집니다.
        }
      }
      const tomas = new Dog('tomas');
      tomas.bark(); // tomas is barking!
      tomas.walk(); // tomas is walking!
  • arguments 객체는 가변 인자 함수를 구현할 때 유용한데, 인수의 개수를 지정해야 줘야하는 타입스크립트에서는 필요가 없는지? (김민석)

    • 타입스크립트에서는 arguments의 단점을 보완한 Rest Parameter을 사용합니다. arguments 객체보다 더 명확하고 타입 안전성도 제공하며, 배열 메서드도 사용할 수 있습니다.

19장

  • ES6의 클래스 문법과 프로토타입 기반 상속의 차이점은? (김민석)
    • 18장의 민정님 질문에 대한 답변으로 대체하겠습니다.
  • 프로토타입 기반 상속과 클래스 기반 상속의 장단점을 비교 (JS에서 다중 상속을 구현하는 방법과 그 한계점) (김주영)
    • 프로토타입 기반 상속
      • 상속 과정이 복잡함
    • 클래스 기반 상속
      • class는 암묵적으로 strict mode가 적용되어 안정성 증가
      • 가독성 좋음
      • 상속 과정이 간단함
    • 다중 상속
  • 프로토타입 - 실 개발에서 프로토타입을 교체하는 경우? (조천산)
    • 거의 없겠지만 있다면 제가 들었던 예시처럼 생성자 함수를 통해 상속하는 경우일 것 같아요. 아마 정말 오래된 코드가 아닌 이상 가독성이 훨씬 좋고 직관적인 class를 쓸 것 같습니다.

@minjeongss
Copy link
Collaborator Author

minjeongss commented Aug 28, 2024

15장

  • p.213, TDZ의 개념이 확실히 이해 가지 않아 더 자세히 알고싶음(+예시) (김주영)

    • TDZ: 변수 호이스팅으로 선언이 된 후, 초기화되지 않은 변수가 머무는 공간
    • 변수 선언 및 초기화 하기 전에 사용되면 사각지대 상태이기에 참조 에러가 발생하는 것

    image

    • const, let 변수, class구문에서 발생
    • var, function import 구문에서 발생X

18장

  • __proto__와 prototype이 사용되는 예시는 무엇이 있는가? (김민정)

    • prototype: 자손에게 넘길 메소드, 변수 정의

      • 모든 객체에 공통으로 적용할 메소드, 속성 정의에 유용
      // 생성자 함수 정의
      function Person(name, age) {
          this.name = name;
          this.age = age;
      }
      
      // prototype을 이용해 메서드 추가
      Person.prototype.sayHello = function() {
          console.log(`Hello, my name is ${this.name}.`);
      };
      
      // Person 객체 생성
      const person1 = new Person('Alice', 30);
      const person2 = new Person('Bob', 25);
      
      // 각 객체에서 sayHello 메서드 호출
      person1.sayHello(); // Hello, my name is Alice.
      person2.sayHello(); // Hello, my name is Bob.
    • __ proto __: 전달받은 메소드, 변수 접근하며, 부모에게 받은 prototype 참조함

      • 객체의 프로토타입 이해, 변경에 유용
      // 객체 생성
      const animal = {
          speak: function() {
              console.log('Animal sound');
          }
      };
      
      // dog 객체 생성
      const dog = {
          bark: function() {
              console.log('Woof!');
          }
      };
      
      // dog의 __proto__를 animal로 설정
      dog.__proto__ = animal;
      
      // dog 객체에서 bark와 speak 메서드 호출
      dog.bark();  // Woof!
      dog.speak(); // Animal sound
    • [참고주소](https://velog.io/@goggling/Prototype%EA%B3%BC-proto-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B01)

  • arguments 객체는 가변 인자 함수를 구현할 때 유용한데, 인수의 개수를 지정해야 줘야하는 타입스크립트에서는 필요가 없는지? (김민석)

    • 타입스크립트에서 사용은 가능하나, 타입 단언을 통한 타입 정의가 필요하기에 안전하지 않아 rest 파라미터 사용이 추천됨
    function sum(){
    	let total=0;
    	for(let i=0; i<arguments.length; i++){
    		total+=arguments[i] as number; //타입 단언
    	}
    	return total;
    }

19장

  • ES6의 클래스 문법과 프로토타입 기반 상속의 차이점은? (김민석)

    • 클래스
      • extends 키워드 사용해 다른 클래스 상속
      • 단일 상속 지원
      • 인터페이스 기능 제공X
    • 프로토타입
      • Object.create()나 new 연산자를 사용해 프로토타입 객체 상속
      • 동적 프로퍼티 추가 가능
  • 프로토타입 기반 상속과 클래스 기반 상속의 장단점을 비교 (JS에서 다중 상속을 구현하는 방법과 그 한계점) (김주영)

    • 프로토타입 기반 상속, 클래스 기반 상속의 장단점
      • 위의 답변
    • 다중 상속 구현
      • 한계점
        • 자바스크립트 언어 자체에서 다중 상속을 허용하지 않음
        • 단, 다중 상속과 유사한 패턴 구현 가능
          • 믹스인된 메서드는 프로토타입 체인에 연결되지 않아, 다중 상속 구조 추적이 어려움
      • 방법
        • 믹스인 활용

          • 여러 객체의 속성과 메서드를 각각 만들고, 다른 객체에 복//사하는 방식
          //프로토타입 기반 상속
          Object.assign(Animal.prototype, fly, swim);
          
          //클래스 기반 상속
          Object.assign(Animal.prototype, fly.prototype, swim.prototype);
  • 프로토타입 - 실 개발에서 프로토타입을 교체하는 경우? (조천산)

    • 코드 테스트
    • 라이브러리 확장
    • 단, 일반적인 상황에선 변경하는 것은 권장되지 않음

@se0kcess
Copy link
Collaborator

se0kcess commented Aug 28, 2024

15장

p.213, TDZ의 개념이 확실히 이해 가지 않아 더 자세히 알고싶음(+예시) (김주영)

  • TDZ는 일시적 사각지대로 let, const 등으로 선언된 변수가 선언은 되었지만 초기화 되지 않아 참조할 수 없는 구간을 말함
{
  // TDZ 시작
  const func = () => console.log(letVar); // 함수 선언만 됨, 참조 불가
  
  // letVar는 여전히 TDZ에 있음
  let letVar = 3; // TDZ 종료, letVar 초기화
  
  func(); // 3 출력 - 이제 letVar에 접근 가능
}

18장

__proto__와 prototype이 사용되는 예시는 무엇이 있는가? (김민정)

  • __proto__는 객체가 자신의 프로토타입에 접근할 때 사용하는 속성
  • prototype은 함수 객체가 가지는 속성으로, 새로운 객체를 생성할 때 그 객체의 프로토타입이 될 객체를 지정함

주요 차이점

  • 존재 위치:

    • __proto__는 모든 객체에 존재
    • prototype은 함수 객체에만 존재
  • 사용 목적:

    • __proto__는 객체의 프로토타입을 참조
    • prototype은 새로 생성될 객체의 프로토타입을 정의
  • 설정 시점:

    • __proto__는 객체 생성 시 자동으로 설정
    • prototype은 함수 정의 시 생성되며, 개발자가 수정 가능

arguments 객체는 가변 인자 함수를 구현할 때 유용한데, 인수의 개수를 지정해야 줘야하는 타입스크립트에서는 필요가 없는지? (김민석)

  • TypeScript에서도 arguments 객체를 사용할 수 있지만 rest 파라미터를 사용하는 것이 더 타입지정에 안전함

19장

ES6의 클래스 문법과 프로토타입 기반 상속의 차이점은? (김민석)

  • 클래스 문법이 더 직관적이고 읽기 쉬움
  • 클래스는 호이스팅되지 않지만, 함수 선언은 호이스팅됨
  • 클래스 내부는 자동으로 strict mode가 적용됨

프로토타입 기반 상속과 클래스 기반 상속의 장단점을 비교 (JS에서 다중 상속을 구현하는 방법과 그 한계점) (김주영)

  • 장점:

    • 프로토타입: 동적으로 속성과 메서드를 추가/수정할 수 있어 유연함
    • 클래스: 문법이 직관적이고, 상속 관계를 명확히 표현할 수 있음
  • 단점:

    • 프로토타입: 복잡한 상속 관계를 표현하기 어려움
    • 클래스: 런타임에 클래스 정의를 변경하기 어려움

프로토타입 - 실제 개발에서 프로토타입을 교체하는 경우? (조천산)

  • 프로토타입 교체의 문제점

    • 프로토타입을 교체하면 해당 객체 타입의 모든 인스턴스에 영향을 미치므로 이는 기존 코드의 동작을 예기치 않게 변경할 수 있움
    • 프로토타입 체인이 길어지면 속성이나 메서드를 찾는 데 더 많은 시간이 걸릴 수 있으므로 성능 저하 유발
    • 새로 추가한 메서드나 속성이 이미 존재하는 것과 이름이 충돌 가능
    • 프로토타입을 수정하면 코드의 동작을 예측하기 어려워져 디버깅과 유지보수가 힘들어짐
    • 라이브러리나 프레임워크 간에 같은 프로토타입을 다르게 수정하면 충돌이 발생할 수 있음
    • 악의적인 코드가 중요한 프로토타입을 수정하여 보안 취약점을 만들 수 있음

이러한 이유로 실제 개발에서 프로토타입을 교체하는 일은 매우 드뭄

@kimjuyoung99
Copy link
Member

kimjuyoung99 commented Aug 28, 2024

질문

15장

- p.213, TDZ의 개념이 확실히 이해 가지 않아 더 자세히 알고싶음(+예시) (김주영)

변수가 선언되었지만 아직 초기화 되지 않는 상태를 말 한다. '선언만 되고 아직 초기화 되지 않는 변수가 머무는 공간’

  • TDZ의 필요 이유 : 프로그래밍 오류를 줄이는데 있음
  • TDZ 동작 방식
    1. 변수 선언 전 : 변수에 접근하려고 하면 ReferenceError 발생
    1. 변수 선언 및 초기화 : 안전하게 사용할 수 있는 단계, 값이 할당되어 접근 및 사용 가능
// let으로 선언된 변수
console.log(beforeLet); // ReferenceError
let beforeLet = "이제 사용 가능!";
console.log(beforeLet); // 출력: "이제 사용 가능!"

// const로 선언된 변수
console.log(beforeConst); // ReferenceError
const beforeConst = "이제 사용 가능!";
console.log(beforeConst); // 출력: "이제 사용 가능!"

18장

- __proto__와 prototype이 사용되는 예시는 무엇이 있는가? (김민정)

  1. proto: 객체의 프로토타입을 직접 접근할 때 사용 (비표준 비권장)
let animal = {
  eats: true
};

let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal; // rabbit의 프로토타입을 animal로 설정

console.log(rabbit.eats); // true
  1. prototype : 생성자 함수의 프로토타입을 설정할 때 사용
function Dog(name) {
  this.name = name;
}

Dog.prototype.bark = function() {
  console.log(this.name + " says Woof!");
};

let myDog = new Dog("Buddy");
myDog.bark(); // "Buddy says Woof!"

- arguments 객체는 가변 인자 함수를 구현할 때 유용한데, 인수의 개수를 지정해야 줘야하는 타입스크립트에서는 필요가 없는지? (김민석)

TypeScript에서도 arguments 객체를 사용할 수 있지만, 대신 rest 파라미터를 사용하는 것이 권장된다.
rest 파라미터는 타입 안정성을 제공하며 더 명확한 문법을 제공한다.

19장

- ES6의 클래스 문법과 프로토타입 기반 상속의 차이점은? (김민석)

  1. 문법적 차이
  • ES6 클래스는 더 간결하고 읽기 쉬운 문법을 제공한다.
  • 프로토타입 방식에서는 prototype 객체를 직접 조작하지만, 클래스에서는 이를 숨긴다(extends 키워드로 상속을 쉽게 구현할 수 있다)
  1. 호이스팅:
  • 함수 선언은 호이스팅되지만, 클래스 선언은 호이스팅되지 않는다.
  • 클래스를 사용하기 전에 반드시 선언해야 한다.

- 프로토타입 기반 상속과 클래스 기반 상속의 장단점을 비교 (JS에서 다중 상속을 구현하는 방법과 그 한계점) (김주영)

프로토타입 기반 상속: 장점: 유연성, 동적 확장 가능 단점: 복잡성, 가독성 저하
클래스 기반 상속: 장점: 직관적인 문법, 더 나은 가독성 단점: 다중 상속 불가능

  • 배열로 한번에 프로토타입을 연결 시켜주게되면 기존 프로토타입처럼 참조할 수가 없기 때문에 프로토타입 체인끼리 연결 시켜주면 다중 상속을 한 것처럼 보이게 할 수는 있다.
  • 믹스인(Mixin) 패턴을 사용

- 프로토타입 - 실 개발에서 프로토타입을 교체하는 경우? (조천산)

  1. 기존 객체의 기능을 확장할 때 (라이브러리 확장)
  2. 라이브러리나 프레임워크에서 기본 객체의 동작을 수정할 때
  3. 폴리필(polyfill)을 구현할 때 : 특정 브라우저에서 지원하지 않는 기능을 구현할 때 사용

예제코드

function MyObject() {
  this.value = 42;
}

MyObject.prototype.getValue = function() {
  return this.value;
};

const obj = new MyObject();
console.log(obj.getValue()); // 출력: 42

// 프로토타입 교체
MyObject.prototype = {
  getValue: function() {
    return this.value * 2;
  }
};

const newObj = new MyObject();
console.log(newObj.getValue()); // 출력: 84
console.log(obj.getValue()); // 출력: 42 (기존 객체는 영향 받지 않음)

@minjeongss
Copy link
Collaborator Author

😮 추가 질문!
프로토타입 기반의 상속이 클래스 기반 상속보다 복잡해서, 클래스를 많이 사용하게 된다고 결론을 지었는데
리액트에선 클래스를 사용하지 않는다고 알고 있습니다.
그렇다면 리액트에서 사용하는 상속 방식은 프로토타입 기반일까요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants