"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Programación orientada a objetos en JS -

Programación orientada a objetos en JS -

Publicado el 2024-11-04
Navegar:316

OOP in JS -

  • Las clases JS son como azúcar sintáctica, no son lo mismo que las clases de otros lenguajes fuertemente tipados.
  • Solo agrega ajuste de sintaxis para que sea familiar para los desarrolladores que vienen de otros idiomas.
  • las clases son un tipo especial de funciones detrás de escena, por lo tanto, pueden escribirse como expresión de clase y como declaración de clase.
## 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'

Puntos de importación:

  • Las declaraciones Fn se elevan mientras que las declaraciones de Clase NO se elevan.
  • También ciudadano de primera clase como Fns, es decir, se puede pasar y devolver desde fns.
  • El cuerpo de la clase siempre se ejecuta en modo estricto, ya sea que activemos el modo estricto o no.
  • Las clases hacen que el código se vea más limpio, con un ruido de caracteres reducido, siempre que sepas cómo se implementa internamente. ** Para convertirse en un experto en JS, debe comprender los intrincados detalles de la implementación del lenguaje, como ocurre con las clases.

Propiedades del acceso: captadores y definidores, es decir, fns que obtienen y establecen el valor. Pero por fuera, todavía parecen propiedades normales.

Las propiedades normales se denominan propiedades de datos.

  • Los captadores y definidores son comunes a todos los objetos en JS, es decir, cada objeto puede tener propiedades captadores y definidores. Estos getter-setter se denominan propiedades de acceso, mientras que las propiedades normales se denominan propiedades de datos.

- Getter y setter son fns que obtienen y establecen un valor, desde fuera parecen propiedades normales.

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.

Métodos estáticos

Ex. Array.from() = Convierte una estructura similar a una matriz en una matriz.
Array.from(document.querySelector('h1'));
Array.from(document.querySelectorAll('h1'));

Ex. .from se adjunta al constructor Array, no a la propiedad prototipo del constructor. Por lo tanto, no todas las matrices heredan esta función.
[1,2,3].desde(); // .from no es una función

Ex. Number.parseFloat(12) es un método estático en el constructor Number, no disponible en variables numéricas.

Creando un método estático.

// 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

Objeto.create():

Se utiliza manualmente para establecer el prototipo de nuestro objeto en cualquier objeto que queramos.
Se utilizará para implementar clases de herencia en blanco y negro.
Herencia prototípica implementada usando esta fn.
Object.create devuelve un objeto vacío.
Funciona de una manera diferente a la que funcionan las clases y fns del constructor.
Todavía existe una idea de herencia prototípica, incluso sin la participación del 'prototipo', el 'constructor()' y el operador 'nuevo'.

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();

Constructor Fn --(.prototipo)--> Persona.prototipo
Instancia de objeto --(proto)--> Persona.prototipo

Funciona igual que funcionó para constructores fn o en clases
No se necesita la propiedad constructor() o .prototype para lograr este objetivo.

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 }  

Formas de crear herencia prototípica:
Constructor Fn
Clases ES6
Objeto.crear

Herencia entre clases usando constructor():

Todas estas técnicas permiten que el objeto busque métodos en su prototipo.
Las clases reales no existen en 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'

Eliminando código redundante del ejemplo anterior:

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' crea un vínculo automáticamente entre la instancia del objeto y su prototipo a través de proto
La idea general de la herencia es que la clase secundaria puede compartir el comportamiento de las clases principales en la cadena del prototipo.
Prototipo[Objeto.prototipo] = nulo; // Se ubica encima de la cadena prototipo.

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
Declaración de liberación Este artículo se reproduce en: https://dev.to/mahf001/oops-in-js-22-5a2n?1 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3