Create class objects in javascript

Класс: базовый синтаксис

В объектно-ориентированном программировании класс – это расширяемый шаблон кода для создания объектов, который устанавливает в них начальные значения (свойства) и реализацию поведения (методы).

На практике нам часто надо создавать много объектов одного вида, например пользователей, товары или что-то ещё.

Как мы уже знаем из главы Конструктор, оператор «new», с этим может помочь new function .

Но в современном JavaScript есть и более продвинутая конструкция «class», которая предоставляет новые возможности, полезные для объектно-ориентированного программирования.

Синтаксис «class»

Базовый синтаксис выглядит так:

class MyClass < // методы класса constructor() < . >method1() < . >method2() < . >method3() < . >. >

Затем используйте вызов new MyClass() для создания нового объекта со всеми перечисленными методами.

При этом автоматически вызывается метод constructor() , в нём мы можем инициализировать объект.

class User < constructor(name) < this.name = name; >sayHi() < alert(this.name); >> // Использование: let user = new User("Иван"); user.sayHi();

Когда вызывается new User(«Иван») :

  1. Создаётся новый объект.
  2. constructor запускается с заданным аргументом и сохраняет его в this.name .

…Затем можно вызывать на объекте методы, такие как user.sayHi() .

Частая ошибка начинающих разработчиков – ставить запятую между методами класса, что приводит к синтаксической ошибке.

Синтаксис классов отличается от литералов объектов, не путайте их. Внутри классов запятые не требуются.

Что такое класс?

Итак, что же такое class ? Это не полностью новая языковая сущность, как может показаться на первый взгляд.

Давайте развеем всю магию и посмотрим, что такое класс на самом деле. Это поможет в понимании многих сложных аспектов.

В JavaScript класс – это разновидность функции.

class User < constructor(name) < this.name = name; >sayHi() < alert(this.name); >> // доказательство: User - это функция alert(typeof User); // function

Вот что на самом деле делает конструкция class User <. >:

  1. Создаёт функцию с именем User , которая становится результатом объявления класса. Код функции берётся из метода constructor (она будет пустой, если такого метода нет).
  2. Сохраняет все методы, такие как sayHi , в User.prototype .

При вызове метода объекта new User он будет взят из прототипа, как описано в главе F.prototype. Таким образом, объекты new User имеют доступ к методам класса.

На картинке показан результат объявления class User :

Можно проверить вышесказанное и при помощи кода:

class User < constructor(name) < this.name = name; >sayHi() < alert(this.name); >> // класс - это функция alert(typeof User); // function // . или, если точнее, это метод constructor alert(User === User.prototype.constructor); // true // Методы находятся в User.prototype, например: alert(User.prototype.sayHi); // sayHi() < alert(this.name); >// в прототипе ровно 2 метода alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

Не просто синтаксический сахар

Иногда говорят, что class – это просто «синтаксический сахар» в JavaScript (синтаксис для улучшения читаемости кода, но не делающий ничего принципиально нового), потому что мы можем сделать всё то же самое без конструкции class :

// перепишем класс User на чистых функциях // 1. Создаём функцию constructor function User(name) < this.name = name; >// каждый прототип функции имеет свойство constructor по умолчанию, // поэтому нам нет необходимости его создавать // 2. Добавляем метод в прототип User.prototype.sayHi = function() < alert(this.name); >; // Использование: let user = new User("Иван"); user.sayHi();

Результат этого кода очень похож. Поэтому, действительно, есть причины, по которым class можно считать синтаксическим сахаром для определения конструктора вместе с методами прототипа.

Читайте также:  Python time struct to timestamp

Однако есть важные отличия:

    Во-первых, функция, созданная с помощью class , помечена специальным внутренним свойством [[IsClassConstructor]]: true . Поэтому это не совсем то же самое, что создавать её вручную. В отличие от обычных функций, конструктор класса не может быть вызван без new :

class User < constructor() <>> alert(typeof User); // function User(); // Error: Class constructor User cannot be invoked without 'new'

Кроме того, строковое представление конструктора класса в большинстве движков JavaScript начинается с «class …»

class User < constructor() <>> alert(User); // class User

Также в дополнение к основной, описанной выше, функциональности, синтаксис class даёт ряд других интересных возможностей, с которыми мы познакомимся чуть позже.

Class Expression

Как и функции, классы можно определять внутри другого выражения, передавать, возвращать, присваивать и т.д.

Пример Class Expression (по аналогии с Function Expression):

Аналогично Named Function Expression, Class Expression может иметь имя.

Если у Class Expression есть имя, то оно видно только внутри класса:

// "Named Class Expression" // (в спецификации нет такого термина, но происходящее похоже на Named Function Expression) let User = class MyClass < sayHi() < alert(MyClass); // имя MyClass видно только внутри класса >>; new User().sayHi(); // работает, выводит определение MyClass alert(MyClass); // ошибка, имя MyClass не видно за пределами класса

Мы даже можем динамически создавать классы «по запросу»:

function makeClass(phrase) < // объявляем класс и возвращаем его return class < sayHi() < alert(phrase); >; >; > // Создаём новый класс let User = makeClass("Привет"); new User().sayHi(); // Привет

Геттеры/сеттеры, другие сокращения

Как и в литеральных объектах, в классах можно объявлять вычисляемые свойства, геттеры/сеттеры и т.д.

Вот пример user.name , реализованного с использованием get/set :

class User < constructor(name) < // вызывает сеттер this.name = name; >get name() < return this._name; >set name(value) < if (value.length < 4) < alert("Имя слишком короткое."); return; >this._name = value; > > let user = new User("Иван"); alert(user.name); // Иван user = new User(""); // Имя слишком короткое.

При объявлении класса геттеры/сеттеры создаются на User.prototype , вот так:

Object.defineProperties(User.prototype, < name: < get() < return this._name >, set(name) < // . >> >);

Пример с вычисляемым свойством в скобках [. ] :

Источник

Classes in JavaScript

In the last article, we introduced some basic concepts of object-oriented programming (OOP), and discussed an example where we used OOP principles to model professors and students in a school.

We also talked about how it’s possible to use prototypes and constructors to implement a model like this, and that JavaScript also provides features that map more closely to classical OOP concepts.

In this article, we’ll go through these features. It’s worth keeping in mind that the features described here are not a new way of combining objects: under the hood, they still use prototypes. They’re just a way to make it easier to set up a prototype chain.

Читайте также:  Add css classes javascript
Prerequisites: Basic computer literacy, a basic understanding of HTML and CSS, familiarity with JavaScript basics (see First steps and Building blocks) and OOJS basics (see Introduction to objects, Object prototypes, and Object-oriented programming).
Objective: To understand how to use the features JavaScript provides to implement «classical» object-oriented programs.

Classes and constructors

You can declare a class using the class keyword. Here’s a class declaration for our Person from the previous article:

class Person  name; constructor(name)  this.name = name; > introduceSelf()  console.log(`Hi! I'm $this.name>`); > > 

This declares a class called Person , with:

  • a name property.
  • a constructor that takes a name parameter that is used to initialize the new object’s name property
  • an introduceSelf() method that can refer to the object’s properties using this .

The name; declaration is optional: you could omit it, and the line this.name = name; in the constructor will create the name property before initializing it. However, listing properties explicitly in the class declaration might make it easier for people reading your code to see which properties are part of this class.

You could also initialize the property to a default value when you declare it, with a line like name = »; .

The constructor is defined using the constructor keyword. Just like a constructor outside a class definition, it will:

  • create a new object
  • bind this to the new object, so you can refer to this in your constructor code
  • run the code in the constructor
  • return the new object.

Given the class declaration code above, you can create and use a new Person instance like this:

const giles = new Person("Giles"); giles.introduceSelf(); // Hi! I'm Giles 

Note that we call the constructor using the name of the class, Person in this example.

Omitting constructors

If you don’t need to do any special initialization, you can omit the constructor, and a default constructor will be generated for you:

class Animal  sleep()  console.log("zzzzzzz"); > > const spot = new Animal(); spot.sleep(); // 'zzzzzzz' 

Inheritance

Given our Person class above, let’s define the Professor subclass.

class Professor extends Person  teaches; constructor(name, teaches)  super(name); this.teaches = teaches; > introduceSelf()  console.log( `My name is $this.name>, and I will be your $this.teaches> professor.`, ); > grade(paper)  const grade = Math.floor(Math.random() * (5 - 1) + 1); console.log(grade); > > 

We use the extends keyword to say that this class inherits from another class.

The Professor class adds a new property teaches , so we declare that.

Since we want to set teaches when a new Professor is created, we define a constructor, which takes the name and teaches as arguments. The first thing this constructor does is call the superclass constructor using super() , passing up the name parameter. The superclass constructor takes care of setting name . After that, the Professor constructor sets the teaches property.

Note: If a subclass has any of its own initialization to do, it must first call the superclass constructor using super() , passing up any parameters that the superclass constructor is expecting.

We’ve also overridden the introduceSelf() method from the superclass, and added a new method grade() , to grade a paper (our professor isn’t very good, and just assigns random grades to papers).

With this declaration we can now create and use professors:

const walsh = new Professor("Walsh", "Psychology"); walsh.introduceSelf(); // 'My name is Walsh, and I will be your Psychology professor' walsh.grade("my paper"); // some random grade 

Encapsulation

Finally, let’s see how to implement encapsulation in JavaScript. In the last article we discussed how we would like to make the year property of Student private, so we could change the rules about archery classes without breaking any code that uses the Student class.

Here’s a declaration of the Student class that does just that:

class Student extends Person  #year; constructor(name, year)  super(name); this.#year = year; > introduceSelf()  console.log(`Hi! I'm $this.name>, and I'm in year $this.#year>.`); > canStudyArchery()  return this.#year > 1; > > 

In this class declaration, #year is a private data property. We can construct a Student object, and it can use #year internally, but if code outside the object tries to access #year the browser throws an error:

const summers = new Student("Summers", 2); summers.introduceSelf(); // Hi! I'm Summers, and I'm in year 2. summers.canStudyArchery(); // true summers.#year; // SyntaxError 

Note: Code run in the Chrome console can access private properties outside the class. This is a DevTools-only relaxation of the JavaScript syntax restriction.

Private data properties must be declared in the class declaration, and their names start with # .

Private methods

You can have private methods as well as private data properties. Just like private data properties, their names start with # , and they can only be called by the object’s own methods:

class Example  somePublicMethod()  this.#somePrivateMethod(); > #somePrivateMethod()  console.log("You called me?"); > > const myExample = new Example(); myExample.somePublicMethod(); // 'You called me?' myExample.#somePrivateMethod(); // SyntaxError 

Test your skills!

You’ve reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you’ve retained this information before you move on — see Test your skills: Object-oriented JavaScript.

Summary

In this article, we’ve gone through the main tools available in JavaScript for writing object-oriented programs. We haven’t covered everything here, but this should be enough to get you started. Our article on Classes is a good place to learn more.

Found a content problem with this page?

This page was last modified on Jul 7, 2023 by MDN contributors.

Your blueprint for a better internet.

Источник

Оцените статью