Автор оригинала: Theofanis Despoudis.
или программирование без использования «это»
Ключевое слово . это
В JavaScript, вероятно, наиболее обсуждаемое ключевое слово в JavaScript только потому, что оно имеет другое поведение в зависимости от того, где вызывается и какой режим окружающей среды включен (строгий против строгого).
Совет: Если вы хотите узнать больше о том, как ключевое слово «Это» работает вы можете прочитать эти отличные статьи: Ключевое слово это для начинающих Простые правила «это» в JavaScript
Я не буду вступить в вступление, как это работает, но вместо этого я сосредоточусь с другой идеей и методом программирования.
То, как это
Ведет себя, злится некоторые программисты, поэтому они решили не использовать его вообще. Я не виню их, так как оно создало так много побочных эффектов и языковых расширений, чтобы не иметь дело с его особенностями (см. Функции стрелки и т. Д., Это связывание и т. Д.), что в конце дня мы можем обойтись без него. Так что теперь давайте попробуем новый способ борьбы с беззаски мир, думая глубоко …
Идея
Главное, что нам нужно помнить, так это то, что функции являются гражданами первого класса в JavaScript. Вы можете использовать их в качестве значений для функциональных параметров или вы можете вернуть функции. Когда вы делаете это, вы создаете закрытие. Закрытие – это внутренняя функция, которая имеет доступ к цепочке переменных внешней (огражденной) функции. Эти переменные являются частными для функции, поэтому они не доступны с помощью областей, которая содержит значение внутреннего функционала прямого средства. Например, посмотрите на эту функцию Adder:
function makeAdder(base) { let current = base; return function(addition) { current += addition; return current; } }
Эта функция примет базовый параметр, и он вернет функцию. Эта функция примет параметр и когда называется доступ к Текущий Переменная, поэтому она сделает дополнение и вернуть результат. Для каждого последующих вызовов он сохранит текущее значение каждый раз.
Таким образом, важно отметить:
Замыкание определяют свою местную лексику, которая действует как частное пространство для функций.
Закрытия являются очень мощной функцией в JavaScript и при правильном использовании можно построить очень хорошие абстракции.
Теперь, когда у нас есть эти знания, мы можем продлить представление о возврате конкретного объекта, который знает, как манипулировать в местной среде. Подумайте об этом как об этом общедоступной API, которое закрытие подвергает. Имя этого Выявление модуля.
Вы можете сказать, что в выявленном шаблоне модуля вы можете определить, какие члены являются общедоступными, а члены которых являются частными. Это делает код более читаемым и проще в использовании.
Вот пример этого:
let counter = (function() { let privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } }; })(); counter.increment(); counter.increment(); console.log(counter.value()); // logs 2
Как вы можете увидеть Privatecounter
Переменная – наши данные, которые нам нужно обрабатывать, и операции являются увеличение
, уменьшение
и значение
Вооруженные этими знаниями у нас есть все необходимые инструменты для программирования без этого, и я докажу это с примером.
Пример
Чтобы продемонстрировать один простой пример о том, как использовать закрытие и функции и нет это
Мы собираемся реализовать простую структуру данных, называемую Дейко Отказ ДУКО ИЛИ Двухсторонняя очередь это Абстрактный тип данных что действует как очередь , для которых элементы могут быть добавлены или удалены из передней (головы), либо сзади (хвоста), его также часто называют Голова-хвост связанный список Как мы собираемся реализовать с помощью связанного списка. Это может звучать сложно, но его нет, и если вы будете следовать по логике, вы сможете понять, как реализовать все необходимые операции, которые должен удовлетворить. Обратите внимание, что, хотя это пример, вы можете применять аналогичные методы для любого объекта, который удерживает состояние, будь то модель объекта, магазин или что-то еще.
Вот необходимые операции.
- создать Создает новый объект декабря.
- ushumpy : Проверяет, если дек-объект пуст.
- Plusbback : Добавляет новый предмет в конце дел.
- Pushfront : Добавляет новый предмет на передней части уд.
- Popback : Удаляет и возвращает последний элемент DECE.
- Попконт : Удаляет и возвращает первый элемент DECE.
Давайте сначала подумаем о том, как представлять наш диск с точки зрения объектов и переменных замыкания. Если у нас есть хорошее представление того, что мы можем легко реализовать операции.
Нам нужна переменная, давайте назовем это данные
Это будет держать каждый предмет на детеныне. Нам также нужны указатели для первого и последнего элемента на DECE. Давайте назовем их голова
и хвост
соответственно. Поскольку это связанный список реализации, нам нужен способ связать каждый элемент друг на друга, так что для каждого элемента нам нужны указатели для следующих и предыдущих элементов. Давайте назовем их Следующий
и Ранее
Отказ Наконец, нам нужно отслеживать, как могут быть предметы, которые мы так давайте назовем это Длина
Отказ
Далее нам нужно группировать переменные в своем нужном месте. Для каждого узла нам нужны данные
и указатели на Следующий
и Ранее
Итак, давайте определим Узел
в виде:
let Node = { next: null, prev: null, data: null};
Для каждого слежения нам нужен голова
, а хвост
и а Длина
Итак, давайте определим Дейко
в виде:
let Deque = { head: null, tail: null, length: 0};
Теперь эти объекты представляют собой спецификацию узла и дел. Нам нужно держать их внутри нашего закрытия:
module.exports = LinkedListDeque = (function() { let Node = { next: null, prev: null, data: null }; let Deque = { head: null, tail: null, length: 0 }; // need to return the public api here })();
Теперь, когда мы создали то, что будут наши переменные закрытия, мы можем реализовать создать
Метод, который так же просто, как:
function create() { return Object.create(Deque);}
Это оно. Недавно построенный дек не имеет элементов. Теперь для ushumpy
метод.
function isEmpty(deque) { return deque.length === 0}
Мы пропускаем декоративный объект, и мы проверяем, что его длина свойство равен нулю. Прохладный.
Теперь для метода Pushfront мы должны выполнить следующие шаги:
- Создать новый
Узел
Отказ - Если ук будет пуст, вы просто назначаете голову и хвост, чтобы указать новый
Узел
Отказ - В противном случае, если декор не пуст, возьмите ток
голова
у слепов и убедитесь, что вы назначаетеРанее
к новомуУзел
и пусть новыйУзел
указать егоСледующий
кголова
Отказ Таким образом, первый элемент будет новымУзел
затем старыйголова
Отказ Нам не нужно забывать обновить DECEголова
указать на новыйУзел
Отказ - Увеличение
Длина
Отказ
function pushFront(deque, item) { // Create a new Node const newNode = Object.create(Node); newNode.data = item; // Grab the current head let oldHead = deque.head; deque.head = newNode; if (oldHead) { // We have at least one item. Prepend new Node in the front oldHead.prev = newNode; newNode.next = oldHead; } else {// The deque is empty. Just assign tail. deque.tail = newNode; } // Update length deque.length += 1; return deque; }
Точно так же мы делаем то же самое для Plusbback
Метод для последнего элемента дел.
function pushBack(deque, item) { // Create a new Node const newNode = Object.create(Node); newNode.data = item; // Grab the current tail let oldTail = deque.tail; deque.tail = newNode; if (oldTail) { // We have at least one item. Append new Node at the back oldTail.next = newNode; newNode.prev = oldTail; } else {// The deque is empty. Just assign head. deque.head = newNode; } // Update length deque.length += 1; return deque; }
Наконец, нам нужно разоблачить наши публичные методы вне закрытия, поэтому мы возвращаем объект экспортируемых нужных методов:
return { create: create, isEmpty: isEmpty, pushFront: pushFront, pushBack: pushBack, popFront: popFront, popBack: popBack }
Все идет нормально. Так как мы его используем? Давайте покажем пример использования, показывающий простое представление структуры:
const LinkedListDeque = require('./lib/deque'); d = LinkedListDeque.create(); LinkedListDeque.pushFront(d, '1'); // [1] LinkedListDeque.popFront(d); // [] LinkedListDeque.pushFront(d, '2'); // [2] LinkedListDeque.pushFront(d, '3'); // [3]<=>[2] LinkedListDeque.pushBack(d, '4'); // [3]<=>[2]<=>[4] LinkedListDeque.isEmpty(d); // false
Обратите внимание, как у нас есть четкое разделение данных и операции против данных. Пока мы удерживаем действительную ссылку на деками, мы можем использовать конкретный LinkedList
Операции с уверенностью.
Его домашнее задание
Да, вы думали, что вы уходите, не практикуете что-нибудь самостоятельно? Для полного понимания того, как вещи работают, и вы получаете ощущение этого типа развития, я предлагаю вам работать над следующими упражнениями. Просто клон/вилка, мой Github Repo здесь и начать работать над ними. (Нет, вы не найдете никаких ответов там Хохохо.)
На основании предыдущих операций реализации удовлетворяют остальным. Реализовать
Popback
иПопконт
Функции, которые удаляют и возвращают первый и последний элемент на DECE соответственно.Эта конкретная реализация DECE использует связанные списки. Разная реализация использует простые объекты массива JavaScript. Внедрить все необходимые операции DECE, используя массив и вызовите его
ArrayDeque
Отказ Помните нетэто
нетНовый
ОтказКакие различия во времени и пространственной сложности вы можете найти для каждого метода
ArrayDeque
иLinkedListdeque
Отказ Запишите свои мысли в Markdown.Еще один способ внедрения DECE заключается в использовании как массива, так и ссылка на LinkedList. Назовите это
Смешанное Отказ В этом случае вы выделяете фиксированный массив размера
БлокДопустим, 64 предмета, где вы помещаете свои предметы. Когда вы нажимаете слишком много элементов в блоке, который превысит размер блока, вы выделяете новый блок, который вы используете связанный список, чтобы связать блоки в форме FIFO. Реализуйте необходимые методы для DECE, используя этот подход. Каковы преимущества и недостатки этой структуры? Запишите свои мысли в Markdown.
В его книге оШаблоны дизайна в JavaScript Автор Addy Osmany отмечает, что один недостаток Раскрытие модуля шаблон Это то, что если частная функция относится к публичной функции, эта публичная функция не может быть переопределена, если нужен патч, поскольку частная функция будет продолжать ссылаться на частную реализацию. Таким образом, шаблон не применяется к государственным членам, только для функций. Разработать способ преодолеть этот недостаток. Подумайте о том, какие зависимости есть и как обратное контроль. Как убедиться, что все частные функции имеют доступ к общественным функциям таким образом, чтобы мы всегда находимся в контроле, что пропускается внутри закрытия, поэтому не беспокоиться о патчах на публичных функциях? Запишите свои мысли в Markdown. Напишите метод под названием
Присоединяйтесь к
Это склеивает 2 деке. Например, звонок
Linkedlistdeque.join (первый, второй)будет добавлять второе внимание в конце первого и вернуть новый декон.
Разработайте неразрушающий механизм прохождения для DECE, чтобы его можно было итерацию в контуре. Для этого примера вы можете использоватьES6 итераторы Отказ Разработайте неразрушающий механизм обратного обхода для DECE, чтобы его можно было итерацию в контуре в обратном порядке.
Присоединяйтесь к движению и опубликуйте свой код на GitHub, который вы сделали реализацию дека без «| ». это
И как хорошо вы знаете, снаружи. Не забудьте упомянуть ваш
Удивительный наставник
Отказ Дополнительные знаки: Используйте любую структуру тестирования, чтобы добавить тесты на все ваши реализации. Не забудьте проверить краевые чехлы.Дополнительные знаки: Изменить реализацию DECE, чтобы разрешить обработку
Взвешенные узлы Отказ Например, вы, когда вы откладываетесь от элемента, вы можете указать вес или приоритетную оценку. Если вы не укажете вес, поведение такое же, как нормальный декон. Если вы укажете вес, необходимый, чтобы убедиться, что после каждой операции последний элемент в списке имеет самый низкий приоритет, а первый элемент в списке имеет самый высокий приоритет. Добавьте тесты, чтобы убедиться, что инвариант. Дополнительные знаки: А
полиномиальный это выражение, которое можно записать как: a * x ^ n + an-1 * x ^ n – 1 + … + A1x ^ 1 + A0 где
a..a0
коэффициенты и п … 1 являются показателями. Дизайн класса DECE, который может представлять многочлен. Добавить методы для Добавление , Вычитание, Умножение и Разделение многочлен. Предположим, что вы проходите только упрощенные полиномы не беспокоят сложных. Добавить тесты, чтобы проверить результаты в порядке. Убедитесь, что во всех ваших методах вы возвращаете результат в качестве нового DECE. Ультраметры : Выберите язык программирования, отличный от JavaScript (Python, Go, C ++ и т. Д.) И реализовать все предыдущие упражнения. Woohoo.
Заключение
Хорошо, я надеюсь, что вы сделали свою домашнюю работу, и вы узнали что-то от этого. Если вы думаете, что преимущества не используют это того стоит, вы также можете проверить это Правила Eslint Plugin где вы можете принять его к своим чеканам. Убедитесь, что вы достигнете консенсуса с вашими коллегами, хотя, как вы могли бы получить сварливые лица, когда они видят вас!