"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > JS의 OOP -

JS의 OOP -

2024-11-04에 게시됨
검색:140

OOP in JS -

  • JS 클래스는 구문 설탕과 비슷하며 다른 강력한 형식의 언어 클래스와는 다릅니다.
  • 다른 언어를 사용하는 개발자에게 친숙할 수 있도록 구문 래핑만 추가합니다.
  • 클래스는 배후에 있는 특별한 유형의 함수이므로 클래스 선언뿐만 아니라 클래스 표현식으로도 작성할 수 있습니다.
## class expression:
const Person = class {
}

## class declaration:
class Person {
  constructor(fName, bYear){
   this.fName = fName;
   this.bYear = bYear;
  }
  calcAge(){
   console.log(2024 - this.bYear);
  }
}

- constructor is a method of this class. Pass values for properties to have in objects created using this fn.
- then set the properties of the object using this.xxx = xxx;
- On using 'new' operator, this constructor will be called automatically and return a new object which will be stored in LHS variable as shown below.
Ex. const ronald = new Person('ronald',1975); // Person { fName: 'ronald', bYear: 1975 }
- Methods are written outside the constructor fn and will be added to the prototype property of the object which can be verified using devConsole.
Ex. ronald.calcAge(); // 49

ronald.__proto__ === Person.prototype; // true

- No commas need to be added while adding multiple methods below the constructor fn inside the class.

## Hence, the above syntax works same as constructor fn syntax but with a familiar syntax of strongly typed class based languages.

## Adding a fn explicitly to the prototype:
Person.prototype.greet = function(){
console.log(`Hey ${this.fName}`);
}
ronald.greet(); // 'Hey ronald'

임팩트 포인트:

  • Fn 선언은 호이스트되지만 클래스 선언은 호이스트되지 않습니다.
  • 또한 Fns와 마찬가지로 일류 시민입니다. 즉, fns로 전달 및 반환될 수 있습니다.
  • 클래스 본문은 엄격 모드 활성화 여부에 관계없이 항상 엄격 모드에서 실행됩니다.
  • 클래스를 사용하면 내부적으로 어떻게 구현되는지 알 수 있으면 문자 노이즈가 줄어들어 코드가 더 깔끔하게 보입니다. ** JS 전문가가 되려면 클래스와 같은 복잡한 언어 구현 세부 사항을 이해해야 합니다.

접속자 속성: Getters & Setters, 즉 값을 가져오고 설정하는 fns입니다. 하지만 겉으로는 여전히 일반 부동산처럼 보입니다.

일반 속성을 데이터 속성이라고 합니다.

  • Getter 및 Settter는 JS의 모든 개체에 공통됩니다. 즉, 모든 개체는 getter 및 setter 속성을 가질 수 있습니다. 이러한 getter-setter를 접근자 속성이라고 하고, 일반 속성을 데이터 속성이라고 합니다.

- Getter & Setter는 외부에서 일반 속성처럼 보이는 값을 가져오고 설정하는 fns입니다.

const account = {
  owner: 'jonas',
  movements: [200,300,100,500],
  get latest(){
    // will return an array with last value. Hence, use pop to get the value.
    return this.movements.slice(-1).pop();
  },
  set latest(mov){
    this.movements.push(mov);
  }
}

account.latest; // 500
account.latest = 50; 
account.latest; // 50

Just like above, classes also support the getter-setter methods but acccessed like using a property syntax.

These are very useful for data validation.

정적 메서드

전. Array.from() = 배열과 유사한 구조를 배열로 변환합니다.
Array.from(document.querySelector('h1'));
Array.from(document.querySelectorAll('h1'));

전. .from은 생성자의 프로토타입 속성이 아닌 배열 생성자에 연결됩니다. 따라서 모든 배열은 이 fn을 상속하지 않습니다.
[1,2,3].from(); // .from은 함수가 아닙니다

전. Number.parseFloat(12)는 Number 생성자의 정적 메소드이며 숫자 변수에서는 사용할 수 없습니다.

정적 메소드 생성.

// Static methods are not inherited. They are not added to prototype.
className.fnName = function(){
  console.log(this); // Entire constructor() which is calling the method
  console.log("JS is awesome")
};
className.fnName();

// Rule =  whatever object is calling the method, 'this' points to that object inside the fn. Hence its simply the entire constructor() above.

//Inside class, we need to use static keyword for adding a static method.
static fnName = function(){
  console.log(this); // can point to the entire class defn
  console.log("JS is awesome")
};

// Static methods and instance methods will be different from each other.
// instance methods will be prototype, hence all instances can have access to them

Object.create():

객체의 프로토타입을 원하는 객체로 설정하는 데 수동으로 사용됩니다.
클래스 흑백 상속을 구현하는 데 사용됩니다.
이 fn을 사용하여 구현된 프로토타입 상속.
Object.create는 빈 객체를 반환합니다.
생성자 fns 및 클래스가 작동하는 방식이 다릅니다.
'prototype', 'constructor()', 'new' 연산자를 사용하지 않고도 프로토타입 상속에 대한 아이디어가 여전히 있습니다.

const PersonProto = {
  // This method will be looked up using __proto__ link
  calcAge(){
    console.log(2024 - this.bYear);
  }
};

// baba will be created, with its prototype set to PersonProto object.
const baba = Object.create(PersonProto);
baba;

baba.name = 'Roger';
baba.bYear = '2000';
baba.calcAge();

생성자 Fn --(.prototype)--> Person.prototype
객체 인스턴스 --(proto)--> Person.prototype

fn 생성자 또는 클래스에서 작동하는 것과 동일하게 작동합니다.
이 목표를 달성하기 위해 constructor() 또는 .prototype 속성이 필요하지 않습니다.

const PersonProto = {
  // This method will be looked up using __proto__ link
  calcAge(){
    console.log(2024 - this.bYear);
  },
  // Noting special with init name, its a normal fn here.
  // This has nothing to with ES6 constructor()
  // Manual way of initialzing an object.
  init(fName, bYear){
    this.fName = fName;
    this.bYear = bYear;
  }
};

// baba will be created, with its prototype set to PersonProto object.
const baba = Object.create(PersonProto);
baba;

baba.name = 'Roger';
baba.bYear = '2000';
baba.calcAge();

baba.__proto__;    // { calcAge: [Function: calcAge] }
baba.__proto__ === PersonProto; //true


const alice = Object.create(PersonProto);
alice.init("alice", 2000);
alice;   // { fName: 'alice', bYear: 2000 }  

프로토타입 상속을 만드는 방법:
생성자 Fn
ES6 클래스
객체.생성

생성자()를 사용한 클래스 간 상속:

이러한 모든 기술을 통해 객체는 프로토타입에서 메서드를 검색할 수 있습니다.
JS에는 실제 클래스가 존재하지 않습니다.

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  // This is the duplicate code, any change in Person won't be reflected here.
  this.firstName = firstName;
  this.bYear = bYear;
  this.course = course;
};

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'

위의 예에서 중복 코드 제거:

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  // Person(firstName, bYear); -> This doesn't work because we are calling it as a regular fn call. 'new' has to be used to call this fn constructor. This fn call is simply a regular fn call, in which 'this' is set 'undefined'. Hence, an error as it cannot set firstName on undefined.
  // We want to set the 'this' inside this fn to be same as inside Person above.
  Person.call(this, firstName, bYear);
  this.course = course;
};

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'

'new'는 proto
를 통해 객체 인스턴스와 프로토타입 사이를 자동으로 연결합니다. 상속의 전체 개념은 하위 클래스가 프로토타입 체인까지 상위 클래스의 동작을 공유할 수 있다는 것입니다.
프로토타입[Object.prototype] = null; // 프로토타입 체인 위에 위치합니다.

const Person = function(firstName, bYear){
  this.firstName = firstName;
  this.bYear = bYear;
};

Person.prototype.calcAge = function(){
  console.log(2024 - this.bYear);
};

const Student = function(firstName, bYear, course){
  Person.call(this, firstName, bYear);
  this.course = course;
};

// Student.prototype = Person.prototype; => This doesn't work because we won't get the prototype chain, rather we will get 
// Constructor fn[i.e Person()]    --------------> Person.prototype
// Constructor fn[i.e Student()]   --------------> Person.prototype
// Object [Matt] __proto__: Student.prototype ---> Person.prototype

// Student.prototype manually linked for lookup to Person.prototype.
// This has to be done here and not after else Object.create will overwrite any of the existing methods like introduce() on it.
Student.prototype = Object.create(Person.prototype);

Student.prototype.introduce = function(){
  console.log(`My name is ${this.firstName} and I study ${this.course}`);
}

const matt = new Student("Matt", 2000, "CSE");
matt.introduce(); //  'My name is Matt and I study CSE'
matt.calcAge();    // 24

matt.__proto__;                   // Person { introduce: [Function (anonymous)] }
matt.__proto__.__proto__;        // { calcAge: [Function (anonymous)] }
matt.__proto__.__proto__.__proto__;   // [Object: null prototype] {}

Student.prototype.constructor = Student;   // [Function: Student]

matt instanceof Student; // true
matt instanceof Person; // true
matt instanceof Object; // true
릴리스 선언문 이 글은 https://dev.to/mahf001/oops-in-js-22-5a2n?1 에서 복제하였습니다. 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제해 주시기 바랍니다.
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3