Рубрики
Без рубрики

Понимание прототипа JavaScript

Слово «прототип» в JavaScript не означает первоначальную версию, которая была быстро собрана вместе. Вместо этого это относится к системе. С меткой JavaScript.

JavaScript, как говорят, является прототипом. Итак, «прототипы» должны быть важной концепцией, верно?

Сегодня я собираюсь объяснить, что такое прототипы, что вам нужно знать, и как эффективно использовать прототипы.

Что такое прототипы?

Прежде всего, Не позволяйте слову «прототип» ввести вас в заблуждение . «Прототип» в JavaScript – это не то же самое, что «прототип» на английском языке. Это не означает начальную версию продукта, которая была быстро собрана вместе.

Вместо этого прототип в JavaScript – это просто слово, которое абсолютно ничего не значит. Мы можем заменить прототип апельсинами, и это может означать одно и то же.

Например, подумайте об Apple. До того, как компьютеры Apple стали популярными, вы, вероятно, подумаете о Apple как о фруктах красного цвета. ” Apple “в Apple Computers не имеет значения изначально – но сейчас это делает.

В случае JavaScript прототип относится к системе. Эта система позволяет вам определять свойства на объектах, которые можно получить через экземпляры объекта.

::: Примечание прототип тесно связан с объектно -ориентированным программированием. Это не имеет смысла, если бы вы не понимали, о чем предназначено программирование, ориентированное на объект.

Я предлагаю вам ознакомиться с Эта вступительная серия о объектно -ориентированном программировании Прежде чем идти дальше. :::

Например, Массив это план для массивов. Вы создаете экземпляр массива с [] или New Array () Анкет

const array = ['one', 'two', 'three']
console.log(array)

// Same result as above
const array = new Array('one', 'two', 'three')

Если вы Консоль.log В этом массиве вы не видите никаких методов. Но все же вы можете использовать такие методы, как конг , Среза , фильтр и карта !

Почему?

Потому что эти методы расположены в прототипе массива. Вы можете расширить __proto__ объект (Chrome Devtools) или <Прототип> Object (Firefox devtools), и вы увидите список методов.

Array.Prototype содержит методы

Firefox журналирует прототип как опытный образец

::: Примечание Оба __proto__ в Chrome и <Прототип> В Firefox указывает на объект прототипа. Они просто написаны по -разному в разных браузерах. :::

Когда вы используете карта , JavaScript ищет карта в самом объекте. Если карта не найден, JavaScript пытается найти прототип. Если JavaScript находит прототип, он продолжает искать карта в этом прототипе.

Итак, правильный Определение для прототипа есть: Объект, где экземпляры могут получить доступ Когда они пытаются искать собственность.

Прототип цепочек

Вот что делает JavaScript, когда вы получаете доступ к недвижимости:

Шаг 1 : JavaScript проверяет, есть ли свойство, доступное внутри объекта. Если да, JavaScript использует свойство сразу.

Шаг 2 : Если свойство не находится внутри объекта, JavaScript проверяет, есть ли прототип. Если есть прототип, повторите шаг 1 (и проверьте, находится ли свойство внутри прототипа).

Шаг 3 : Если прототипов больше не осталось, а JavaScript не может найти свойство, оно выполняет следующее:

  • Возвращает неопределенное (Если вы пытались получить доступ к недвижимости).
  • Бросает ошибку (если вы пытались вызвать метод).

Схематически, вот как выглядит процесс:

Пример цепочки прототипа

Допустим, у нас есть ЧЕЛОВЕК класс. У нас также есть Разработчик Подкласс, который наследует от ЧЕЛОВЕК Анкет ЧЕЛОВЕК S имеет Sayhello Метод и Разработчики иметь код метод

Вот код для Человек

class Human {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastname = lastName
  }

  sayHello () {
    console.log(`Hi, I'm ${this.firstName}`)
  }
}

::: Примечание ЧЕЛОВЕКРазработчик ниже) можно записать с функциями конструктора. Если мы используем функции конструктора, Прототип становится более ясным, но создание подклассов становится сложнее. Вот почему я показываю пример с классами. (См. Эта статья для 4 различных способов использования объектно -ориентированного программирования).

Вот как бы ты написал ЧЕЛОВЕК Если вы использовали конструктор вместо этого.

function Human (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

Human.prototype.sayHello = function () {
  console.log(`Hi, I'm ${this.firstName}`)
}

:::

Вот код для Разработчик Анкет

class Developer extends Human {
  code (thing) {
    console.log(`${this.firstName} coded ${thing}`)
  }
}

A Разработчик экземпляр может использовать оба код и скажи привет потому что эти методы расположены в цепочке прототипа экземпляра.

const zell = new Developer('Zell', 'Liew')
zell.sayHello() // Hi, I'm Zell
zell.code('website') // Zell coded website

Если вы Консоль.log Пример, вы можете увидеть методы в цепочке прототипа.

Прототипическое делегирование/прототипа наследование

Прототипная делегирование и прототипальное наследование означают одно и то же.

Они просто говорят, что мы используем систему прототипа – где мы помещаем свойства и методы в Прототип объект.

Должны ли мы использовать прототипную делегирование?

Поскольку JavaScript является языком на основе прототипов, мы должны использовать прототипную делегирование. Верно?

Не совсем.

Я бы сказал, что это зависит от того, как вы пишете объектно -ориентированное программирование. Имеет смысл использовать прототипы, если вы используете классы, потому что они более удобны.

class Blueprint {
  method1 () {/* ... */}
  method2 () {/* ... */}
  method3 () {/* ... */}
}

Но имеет смысл не использовать прототипы, если вы используете заводские функции.

function Blueprint {
  return {
      method1 () {/* ... */}
      method2 () {/* ... */}
      method3 () {/* ... */}
  }
}

Опять читай Эта статья Для четырех разных способов записи объектно -ориентированного программирования.

Последствия для производительности

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

Настраивать

Мы можем использовать Производительность.now Чтобы зарегистрировать временную метку перед выполнением каких -либо операций. После запуска операций мы будем использовать Производительность.now Чтобы снова зарегистрировать метку времени.

Затем мы получим разницу в временных метках, чтобы измерить, сколько времени заняли операции.

const start = performance.now()
// Do stuff
const end = performance.now()

const elapsed = end - start
console.log(elapsed)

Я использовал Perf функция, чтобы помочь с моими тестами:

function perf (message, callback, loops = 1) {
  const startTime = performance.now()
  for (let index = 0; index <= loops; index++) {
    callback()
  }
  const elapsed = performance.now() - startTime
  console.log(message + ':', elapsed)
}

Примечание: вы можете узнать больше о Производительность.now в Эта статья Анкет

Эксперимент № 1: Использование прототипов против не использования прототипов

Во -первых, я проверил, сколько времени требуется, чтобы получить доступ к методу с помощью прототипа против другого метода, который находится в самом объекте.

Вот код:

class Blueprint () {
  constructor () {
    this.inObject = function () { return 1 + 1 }
  }

  inPrototype () { return 1 + 1 }
}

const count = 1000000
const instance = new Blueprint()
perf('In Object', _ => { instance.inObject() }, count)
perf('In Prototype', _ => { instance.inPrototype() }, count)

Средние результаты суммированы в этой таблице следующим образом:

В объекте 3 мс 15 мс
В прототипе 2 мс 12 мс

Примечание. Результаты из Devtools Firefox. Читать это Чтобы понять, почему я только сравниваю с Firefox.

Вердикт: не имеет значения, используете ли вы прототипы или нет. Это не изменится, если вы не запустите> 1 миллион операций.

Эксперимент № 2: Классы против заводских функций

Мне пришлось запустить этот тест, так как я рекомендую использовать прототипы, когда вы используете классы, и не использовать прототипы при использовании заводских функций.

Мне нужно было проверить, было ли создание заводских функций значительно медленнее, чем создание классов.

Вот код.

// Class blueprint
class HumanClass {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }

  sayHello () {
    console.lg(`Hi, I'm ${this.firstName}}`)
  }
}

// Factory blueprint
function HumanFactory (firstName, lastName) {
  return {
    firstName,
    lastName,
    sayHello () {
        console.log(`Hi, I'm ${this.firstName}}`)
      }
  }
}

// Tests
const count = 1000000
perf('Class', _ => { new HumanClass('Zell', 'Liew') }, count)
perf('Factory', _ => { HumanFactory('Zell', 'Liew') }, count)

Средние результаты суммированы в таблице следующим образом:

Класс 5 мс 18 мс
Фабрика 6 мс 18 мс

Вердикт: не имеет значения, используете ли вы класс или заводские функции. Это не изменится, даже если вы запустите> 1 миллион операций.

Заключение о тестировании производительности

Вы можете использовать классы или заводские функции. Вы решите использовать прототипы, или вы можете не делать этого. Это действительно зависит от вас.

Нет необходимости беспокоиться о производительности.

Спасибо за чтение. Эта статья была первоначально размещена на Мой блог Анкет Подпишитесь на мой информационный бюллетень Если вы хотите больше статей, чтобы помочь вам стать лучшим разработчиком Frontend.

Оригинал: “https://dev.to/zellwk/understanding-javascript-prototype-5187”