Давайте разоблачим мифы об операторе new в JavaScript

Давайте разоблачим мифы об операторе new в JavaScript

От автора: в минувшие выходные я закончил работу над JavaScript: The Hard Parts Уилла Сентанса. Это может показаться не самым великолепным способом провести выходные, но я действительно развлекся и расслабился, заканчивая курс. Он коснулся функционального программирования, функций более высокого порядка, замыканий и асинхронного JavaScript.

Для меня основной темой курса было то, как он расширил подходы JavaScript к объектно-ориентированному программированию (ООП) и демистифицировал магию оператора new. Теперь у меня есть хорошо продуманное понимание того, что происходит под капотом, когда используется оператор new JavaScript.

Объектно-ориентированное программирование в JavaScript

Объектно-ориентированное программирование (ООП) — это парадигма программирования, основанная на концепции «объектов». Данные и функции (атрибуты и методы) объединены внутри объекта.

Объект в JavaScript представляет собой набор пар ключ-значение. Эти пары ключ-значение являются свойствами объекта. Свойством может быть массив, функция, сам объект или любой примитивный тип данных, такой как строки или целые числа.

Какие методы мы используем в нашем инструменте JavaScript для создания объекта?

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

Предположим, что мы создаем пользователей в игре, которую мы только что разработали. Как мы будем хранить данные пользователя, такие как их имена, очки и методы реализации, такие как увеличение очков? Вот два варианта создания базового объекта.

Вариант 1 – обозначение объектного литерала

let user1 = {
  name: "Taylor",
  points: 5,
  increment: function() {
 user1.points++;
  }
};

Объектный литерал JavaScript — это список пар имя-значение, завернутый в фигурные скобки. В приведенном выше примере создается объект user1, и связанные с ним данные хранятся внутри него.

Вариант 2 —  Object.create()

Object.create(proto, [ propertiesObject ])

Методы Object.create принимают 2 аргумента:

proto: объект, который должен быть прототипом вновь созданного объекта. Это должен быть object или null.

propertiesObject: свойства нового объекта. Необязательный аргумент.

По факту, вы передаете в Object.create объект, который вы хотите наследовать, и он возвращает новый объект, который наследуется от объекта, который вы ему передали.

let user2 = Object.create(null);
user2.name = "Cam";
user2.points = 8;
user2.increment = function() {
  user2.points++;
}

Варианты создания базового объекта выше повторяются. Для этого требуется, чтобы каждый из них был создан вручную.

Как это обойти?

Решения

Решение 1 – генерация объектов через функцию

Простое решение – написать функцию для создания новых пользователей.

function createUser(name, points) {
  let newUser = {};
  newUser.name = name;
  newUser.points = points;
  newUser.increment = function() {
 newUser.points++;
  };
  return newUser;
}

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

let user1 = createUser("Bob", 5);
user1.increment();

Однако функция increment в приведенном выше примере является только копией исходной функции increment. Это не очень хороший способ написать код, так как любые потенциальные изменения в функции должны выполняться вручную для каждого объекта.

Решение 2 – использование прототипной природы JavaScript

В отличие от объектно-ориентированных языков, таких как Python и Java, JavaScript не имеет классов. Он использует концепцию прототипов и цепочек прототипов для наследования.

Когда вы создаете новый массив, вы автоматически получаете доступ к встроенным методам, таким как Array.join, Array.sort и Array.filter. Это связано с тем, что объекты массива наследуют свойства от Array.prototype.

Давайте разоблачим мифы об операторе new в JavaScript

Каждая функция JavaScript имеет свойство prototype, которое по умолчанию пусто. Вы можете добавить функции к этому свойству прототипа, и в этой форме он известен как метод. Когда унаследованная функция выполняется, значение этого указывает на наследующий объект.

function createUser(name, points) {
  let newUser = Object.create(userFunction);
  newUser.name = name;
  newUser.points = points;
  return newUser;
}
let userFunction = {
  increment: function() {this.points++};
  login: function() {console.log("Please login.")};
}
let user1 = createUser("Bob", 5);
user1.increment();

Когда был создан объект user1, была создана цепочка прототипов с функцией userFunction.

Когда user1.increment () находится в стеке вызовов, интерпретатор будет искать user1 в глобальной памяти. Затем он будет искать функцию increment, но не найдет ее. Интерпретатор рассмотрит следующий объект в цепочке прототипов и найдет там функцию increment.

Решение 3 – new и this

Давайте разоблачим мифы об операторе new в JavaScript

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

Оператор new используется для создания экземпляра объекта, который имеет функцию-конструктор.

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

создание нового объекта

привязку this к объекту

Объектом прототипа функции конструктора становится свойство __proto__ нового объекта

Возвращается объект из функции

Это фантастика, потому что автоматизация приводит к менее повторяемому коду!

function User(name, points) {
 this.name = name; 
 this.points = points;
}
User.prototype.increment = function(){
 this.points++;
}
User.prototype.login = function() {
 console.log(“Please login.”)
}
let user1 = new User(“Dylan”, 6);
user1.increment();

Используя шаблон прототипа, каждый метод и свойство добавляются непосредственно на прототипе объекта.

Интерпретатор пробежит по прототипной цепочке и найдет функцию increment под свойством прототипа User, который сам по себе также является объектом с информацией внутри него. Помните — все функции в JavaScript также являются объектами. Теперь, когда интерпретатор нашел то, что ему нужно, он может создать новый локальный контекст выполнения для запуска user1.increment ().

Замечание: Разница между __proto__ и прототипом

Если вы уже запутались в __proto__ и прототипе, не волнуйтесь! Далеко не вы один запутались. Прототип — это свойство функции-конструктора, которое определяет, что станет свойством __proto__ на построенном объекте. Таким образом, __proto__ является созданной ссылкой, и эта ссылка называется прототипом цепной связи.

Решение 4 – синтаксический сахар ES6

Давайте разоблачим мифы об операторе new в JavaScript

Другие языки позволяют нам писать наши общие методы внутри самого объекта-конструктора. В ECMAScript6 введено ключевое слово class, которое позволяет нам писать классы, которые походят на обычные классы других классических языков. На самом деле это синтаксический сахар над прототипным поведением JavaScript.

class User {
  constructor(name, points) {
 this.name = name;
 this.points = points;
  }
  increment () {
 this.points++;
  }
  login () {
 console.log("Please login.")
  }
}
let user1 = new User("John", 12);
user1.increment();

В решении 3 соответствующие методы были точно реализованы с использованием User.prototype.functionName. В этом решении те же результаты достигаются, но синтаксис выглядит более чистым.

Заключение

Теперь мы узнали больше о различных вариантах, которые мы имеем в JavaScript для создания объектов. Хотя объявления классов и оператор new относительно просты в использовании, важно понять, что автоматизировано.

Повторим, следующие действия автоматизируются при вызове функции конструктора с помощью new:

создание нового объекта

привязку this к объекту

Объектом прототипа функции конструктора становится свойство __proto__ нового объекта

Возвращается объект из функции

Автор: Cynthia Lee

Источник: https://medium.freecodecamp.org/

Редакция: Команда webformyself.

Современные тенденции и подходы в веб-разработке

Узнайте алгоритм быстрого профессионального роста с нуля в сайтостроении

Узнать подробнее

Курс по TypeScript

Прямо сейчас посмотрите курс по TypeScript!

Смотреть курс

Метки:

Похожие статьи:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree