Пожалуйста, забудьте все объектно-ориентированные знания, которые вы узнали раньше. Просто рассмотрите гоночную ситуацию здесь. Да, это гонки.
Недавно я смотрю 24 часа Le Mans, популярного события во Франции. Самый быстрый автомобиль называется прототипом Ле -Мана. Хотя эти автомобили производятся производителями, такими как «Audi» или «Peugeot», они не те автомобили, которые вы видите на улице или на шоссе. Они сделаны специально для высокоскоростных событий на выносливость.
Производитель вкладывает огромные суммы денег для разработки, проектирования и изготовления этих прототиповых автомобилей, и инженеры всегда стараются сделать этот проект до крайности. Они провели различные эксперименты на сплавах, биотопливе, технологии торможения, составной композиции и характеристиках безопасности шин. Со временем некоторые методы в этих экспериментах неоднократно улучшались и входили в основную линейку продуктов автомобилей. Некоторые из технологий в автомобиле, с которой вы едете, могли быть дебютированы на гоночном прототипе.
Вы также можете сказать, что эти основные транспортные средства наследуют технические прототипы от гоночных автомобилей.
До сих пор у нас есть основа для обсуждения прототипа и вопросов наследования в JavaScript. Хотя это не так хорошо, как классический шаблон наследования, который вы знаете в C ++, Java или C#, он такой же мощный и потенциально более гибкий.
JavaScript полон объектов, что относится к объектам в традиционном смысле, то есть «единственной сущности, которая содержит состояние и поведение». Например, массив в JavaScript - это объект, который содержит несколько значений и содержит методы push, обратный и POP.
var myarray = [1, 2]; myarray.push (3); myarray.reverse (); myarray.pop (); var length = myarray.length;
Теперь вопрос в том, откуда взялся толчок? Статические языки, которые мы упоминали ранее, используют «синтаксис класса» для определения структуры объектов, но JavaScript - это язык без «синтаксиса класса» и не может определить каждый объект массива, используя синтаксис массива «класс». И поскольку JavaScript - это динамичный язык, мы можем разместить методы на объекты, поскольку мы действительно нуждаемся в них. Например, следующий код определяет точечный объект, используемый для представления точки в двухмерном пространстве, а также определяет метод добавления.
var point = {x: 10, y: 5, add: function (orepoint) {this.x += otherpoint.x; this.y += otherpoint.y; }};Тем не менее, вышеуказанные практики не очень масштабируемы. Нам нужно убедиться, что каждый объект точки содержит метод добавления, и мы также хотим, чтобы все объекты точек обменивались реализацией одного и того же метода добавления, вместо того, чтобы вручную добавлять этот метод к каждому объекту точки. Вот где прототип вступает в игру.
В JavaScript каждый объект остается скрытым - ссылка на другой объект, также известный как прототип. Массив, который мы создали перед ссылкой на объект прототипа, как и объекты точки, которые мы создали сами. Как упомянуто выше, прототипы ссылки скрыты, но существуют также реализации Ecmascript (официальное имя JavaScript), которые могут получить доступ к этой ссылке на прототип через атрибут __proto__ объекта (например, Google Chrome). Концептуально, мы можем рассматривать объекты как отношения, аналогичные тем, которые представлены на рисунке 1-прототипа.
Рисунок 1
Заглядывая в будущее, разработчики смогут использовать функцию object.getPrototypoF вместо атрибута __proto__ для получения ссылок на прототип объекта. На момент написания этой статьи функция object.getPrototypeOF уже может использоваться в браузерах Google Chrome, Firefox и IE9. Больше браузеров будет реализовать эту функцию в будущем, потому что она уже является частью стандарта Ecmascript. Мы можем использовать следующий код, чтобы доказать, что созданные нами объекты Myarray и Dot относятся к двум различным объектам прототипа.
Для остальной части этой статьи я буду использовать функции __proto__ и object.getPrototypoF, главным образом потому, что __proto__ легче идентифицировать на графиках и предложениях. Следует помнить, что он (__proto__) не является стандартным, а функция object.getPrototypoF - это рекомендуемый метод для просмотра прототипов объектов.
Что делает прототип таким особенным?
Мы не ответили на этот вопрос: откуда происходит толчок в массиве? Ответ: это происходит от объекта прототипа Myarray. Рисунок 2 представляет собой скриншот отладчика сценария в Chrome. Мы назвали метод object.getprototypoof для просмотра объекта прототипа Myarray.
Рисунок 2
Обратите внимание, что в объекте прототипа Myarray есть много методов, включая методы, называемые Push, POP и обратным методом в примерах кода. Следовательно, метод push включает в себя объект прототипа, но как на него ссылается метод Myarray?
myarray.push (3);
Первый шаг к пониманию того, как это работает, состоит в том, чтобы понять, что прототип не особенный. Прототип - это просто нормальный объект. Вы можете добавить методы, свойства в прототип и рассматривать их как другие объекты JavaScript. Однако, чтобы применить заявление «свиньи» в романе Джорджа Оруэлла «Животная ферма» - все объекты должны быть равными, но некоторые объекты (те, кто следит за правилами), более равны, чем другие.
Прототип объектов в JavaScript действительно особенные, потому что они следуют следующим правилам. Когда мы сообщаем JavaScript, что мы хотим вызвать метод разжигания объекта или прочитать свойство x объекта, время выполнения сначала будет искать сам объект. Если время выполнения не может найти то, что он хочет, оно следует за ссылкой __proto__ и прототипом объектов, чтобы найти члена. Когда мы называем метод толкания Myarray, JavaScript не находит метод push на объекте Myarray, а на объекте прототипа Myarray, поэтому JavaScript вызывает этот метод (см. Рисунок 3).
Рисунок 3
Поведение, описанное выше, относится к самому объекту, унаследовавшему любой метод или свойство на прототипе. В JavaScript наследование фактически достигается без использования синтаксиса класса. Как и автомобиль, который наследует соответствующую технологию от гоночного прототипа, объект JavaScript также может наследовать функциональные функции от объекта прототипа.
На рисунке 3 также показано, что каждый объект массива также может поддерживать свое собственное состояние и членов. Запрашивая атрибут длины Myarray, JavaScript получит значение атрибута длины в Myarray без чтения соответствующего значения в прототипе. Мы можем «перезаписать» метод push, добавив такой метод, как Push к объекту. Это эффективно скрывает реализацию метода Push в прототипе.
Реальная магия прототипов в JavaScript заключается в том, как несколько объектов поддерживают ссылки на один и тот же объект прототипа. Например, если мы создадим два массива, как это:
var myarray = [1, 2]; var yourarray = [4, 5, 6];
Затем эти два массива будут иметь один и тот же объект прототипа, а следующий код оценивается на True:
Object.getPrototypeof (myarray) === object.getPrototypeof (yourarray);
Если мы обратимся к методу push на двух объектах массива, JavaScript будет искать метод Push, разделенный на прототипе.
Рисунок 4
Объекты прототипа в JavaScript предоставляют функции наследования, и в то же время реализуется совместное использование этого метода. Прототип также прикован. Другими словами, поскольку объект прототипа - это просто объект, один объект прототипа можно поддерживать к ссылке на другой объект прототипа. Если вы вернетесь на рис. 2, вы увидите, что свойство __proto__ прототипа является неверным значением, указывающим на другой прототип. Когда JavaScript ищет участников, таких как метод push, он проверяет каждый объект вдоль эталонной цепи прототипа, пока она не найдет, или достигнет конца цепочки прототипа. Прототипы цепочек открывают гибкий путь для наследования и совместного использования.
Следующий вопрос, который вы можете задать: как мне настроить прототип ссылок на эти пользовательские объекты? Например, точечный объект, используемый ранее, как я могу добавить метод добавления в объект прототипа и наследовать метод из множественных точечных объектов? Прежде чем ответить на этот вопрос, нам нужно посмотреть на функции.
Функции в JavaScript также являются объектами. Такое утверждение приносит несколько важных результатов, и мы не будем охватывать все вопросы в этой статье. Среди них возможность назначать функцию переменной и передавать функцию в качестве параметра другой функции представляет собой основную парадигму современного выражения программирования JavaScript.
На что нам нужно обратить внимание, так это то, что сама функция является объектом, поэтому функция может иметь свои собственные методы, свойства и ссылаться на объект прототипа. Давайте обсудим значение следующего кода.
// это вернет true: typeof (array) === "function" // Такое выражение также: object.getPrototypeof (массив) === object.getPrototypeof (function () {}) // Такое выражение одинаково: Array.prototype!Первая строка в коде доказывает, что массив в JavaScript является функцией. Посмотрим, как вызвать функцию массива, чтобы создать новый объект массива. Следующая строка кода доказывает, что объект массива использует тот же прототип, что и любой другой объект функции, точно так же, как мы видим, что тот же прототип используется между объектами массива. Последняя строка кода доказывает, что функция массива имеет свойство прототипа, и это свойство прототипа указывает на действительный объект. Это свойство прототипа очень важно.
Каждый объект функции в JavaScript имеет свойство прототипа. Никогда не путайте атрибут __proto__ этого свойства прототипа. Они имеют разные цели, и они не указывают на один и тот же объект.
// return trueObject.getPrototypeof (массив)! = Array.prototype
Array .__ Proto__ обеспечивает прототип массива. Пожалуйста, рассматривайте его как объект, унаследованный функцией массива.
Array.protoype предоставляет объекты прототипа для всех массивов. То есть он обеспечивает прототип объектов объектов массива, таких как Myarray, а также содержит методы, которые все массивы будут наследовать. Мы можем написать какой -то код, чтобы доказать этот факт.
// truearray.prototype == object.getPrototypeof (myarray) // Это также truearray.prototype == object.getPrototypeof (yourarray);
Мы также можем использовать эти новые знания для перекрашения предыдущей диаграммы.
Рисунок 5
Основываясь на том, что вы знаете, представьте процесс создания нового объекта и создания нового объекта как массив. Одним из способов является использование следующего кода.
// Создать новый пустой объект var o = {}; // Унаследованный от того же прототипа, объект массива o .__ Proto__ = Array.prototype; // Теперь мы можем вызвать любой метод массива ... O.Push (3);Хотя этот код интересен и работает, проблема в том, что не каждая среда Javascript поддерживает свойства записи __proto__ объекта. К счастью, JavaScript имеет стандартный механизм для создания объектов. Это требует только одного оператора для создания новых объектов, и установил ссылку __proto__ нового объекта, то есть «новый» оператор.
var o = new Array (); O.Push (3);
Новый оператор в JavaScript имеет три основные задачи. Во -первых, это создает новый пустой объект. Далее он установит свойство __proto__ нового объекта, чтобы соответствовать свойствам прототипа вызываемой функции. Наконец, оператор вызывает функцию, передавая новый объект как ссылку «этот». Если вы хотите расширить две последние строки кода, это станет следующей ситуацией:
var O = {}; o .__ Proto__ = Array.prototype; array.call (o); o.push (3);Метод вызова функции позволяет указать объект, на который ссылается «этот» внутри функции при вызове функции. Конечно, автор функции должен реализовать такую функцию в этом случае. Как только автор создает такую функцию, его можно назвать конструктором.
Конструктор
Конструкторы такие же, как обычные функции, но имеют следующие два специальных свойства.
Массив является примером конструктора. Функция массива должна использоваться с новым оператором, а первоначальная буква массива капитализируется. JavaScript включает массив в качестве встроенной функции, и любой может написать свой собственный конструктор. На самом деле, мы можем наконец написать конструктор для ранее созданных объектов точек.
var point = function (x, y) {this.x = x; this.y = y; this.add = function (orepoint) {this.x += orethpoint.x; this.y += otherpoint.y; }} var p1 = новая точка (3, 4); var p2 = новая точка (8, 6); p1.add (p2);В приведенном выше коде мы используем новый оператор и функцию точки для построения объекта точки, который имеет атрибуты x и y и метод добавления. Вы можете представить конечный результат, как показано на рисунке 6.
Рисунок 6
Проблема сейчас в том, что в каждом из наших объектов точечных объектов все еще есть отдельный метод добавления. Используя прототип и наследование, которое мы изучили, мы бы предпочли перенести метод добавления точечного объекта из каждого экземпляра точки в точку. Прототип. Чтобы достичь эффекта унаследования метода добавления, все, что нам нужно сделать, это изменить точку. Прототип объект.
var point = function (x, y) {this.x = x; this.y = y;} точка this.y += forepoint.y;} var p1 = новая точка (3, 4); var p2 = новая точка (8, 6); p1.add (p2);Миссия сделана! Мы только что завершили режим наследования прототипа в JavaScript!
Рисунок 7
Суммировать
Я надеюсь, что эта статья поможет вам раскрыть тайну концепций прототипа JavaScript. Сначала я увидел, как прототип позволил объекту наследовать функции от других объектов, а затем увидел, как объединить новый оператор и конструктор для построения объекта. То, что упоминается здесь, является лишь первым шагом к разблокировке мощности и гибкости прототипа объекта. Эта статья побуждает вас открыть для себя и изучить новую информацию о прототипах и языках JavaScript.
Также, пожалуйста, ездите осторожно. Вы никогда не узнаете, какие (ошибочные) технологии эти транспортные средства, путешествующие по дороге, наследуют от своих прототипов.
Оригинальная ссылка: Скрипт -мусор перевод: Bole Online - Emje