(или одолжить степлер)

Привет! Я Дауд, разработчик JavaScript с большим опытом работы в сфере образования. Я попытаюсь объяснить некоторые концепции JS для начинающих и среднего уровня с помощью аналогий, примеров кода и *zero* foo и bar (обещаю!) Не стесняйтесь обращаться ко мне, если у вас есть какие-либо вопросы о том, что я написал.

Предпосылки:

Просто немного синтаксиса ES6, например оператор распространения и классы. Это поможет понять «область охвата», «контекст» и this, но не обязательно для понимания этого поста и начала использования прототипов.

Добро пожаловать

После нескольких энергичных раундов интервью вы сделали это! Вы новый сотрудник Компании, и пришло время получить приветственный набор. Вещи немного бессистемны, кажется, никто официально не принял вас на борт, но рядом есть услужливый коллега, чтобы привести в порядок ваши приветственные документы и передать вам и степлер (все для себя!). Внезапно улыбнувшись, она строго смотрит тебе в глаза и говорит:

«Этот степлер для вас. Это только для тебя».

Почти так же быстро все возвращается к веселым шуткам, и через несколько мгновений пришло время найти свой стол. Понятно, что, держа в руках набор из трех отдельных страниц формата А4 и степлер, первое, что вы делаете, это скрепляете их вместе.

Большой! Ваш новый блестящий степлер работает именно так, как вы и ожидали.

Через несколько часов после того, как вы устроились за вашим компьютером, потрепанный, небритый парень представляется как «Джон». Вы чувствуете, что он был здесь в течение очень долгого времени. Джон, похоже, сам держит в руках пачку отдельных документов:

«Это степлер?» — спрашивает он. «Когда я присоединился, они не раздавали их. Могу ли я это одолжить?"

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

Джон выглядит менее чем впечатленным; бросая на вас последний взгляд, который, кажется, кричит: «Вы правда собираетесь заставить меня пройти по коридору за степлером?», он неторопливо направляется к офису вашего услужливого коллеги.

Теперь у Джона есть собственная функция staple(). Несмотря на то, что функции staple() на newEmployee и jon идентичны, в памяти компьютера они существуют дважды.

Сокращение

«Мы потратили сколько на степлеры?!» Босс стоит над своим столом, просматривая последний отчет из бюджетного отдела, думая о своей 6-летней дочери и ее постоянных приставаниях к бассейну. Он смотрит на свой стол и на неиспользованный степлер Swingline, который лежит там годами. «Почему у каждого есть собственныйстеплер? Они все могут просто попросить использовать мою».

Начальник тут же звонит в HR: «Отныне я хочу попробовать давать новобранцам их собственные документы, но перестаньте давать им степлеры! Они могут одолжить мой степлер, если он им понадобится».

Ваш услужливый коллега хлопает вас по плечу. «Извините, я только что разговаривал с HR, вы должны официально пройти регистрацию через них. Кое-что о новой политике. О, и мне нужен твой степлер обратно.

Сейчас есть только один staple(): он theBoss. Помните, что theBoss — это просто переменная, которую мы используем для ссылки на Employee.prototype; функция существует как Employee.prototype.staple().

Вызов конструктора(new Employee) заполняет новый объект с помощью слова this, вызывая функцию из внутри него. Таким образом, this — это человек, которому «помогают», то есть this становится jon, когда звонят jon.staple(), и newEmployee, когда звонят newEmployee.staple(). Для простоты this используется только тогда, когда вы собираетесь использовать прототипы, так как код будет жить в функциях «где-то еще» вверх по цепочке прототипов и должен иметь слово для ссылки на место, где он вызывается.

Последнее слово: стрелочные функции не имеют «контекста», а это означает, что this вернется к контексту предыдущей области. Иногда это чрезвычайно полезно, но это «Основы наследования», поэтому я не буду углубляться; просто знайте, что this будет ссылаться на объект, в котором вызывается функция, только если он написан старым добрым function ().

Вы возвращаете степлер боссу с вежливым, но довольно робким «спасибо». Он сияет; он может видеть, как маленькая Эбигейл мгновенно надевает нарукавные повязки. «Да, это прекрасно», — думает он. «Давайте сделаем эту официальную процедуру».

Далее следует «синтаксический сахар», означающий более чистый и простой способ написания точно такой же функциональности. Стоит повторить: class в JavaScript, в отличие от объектно-ориентированных языков, просто вызывается функция-конструктор и помещаются методы в общий прототип (как показано выше).

Менеджер среднего звена заметил ваш свежий энтузиазм и знает, что вы новичок; она хочет, чтобы ты был в их команде. Бросившись к вам, довольно восторженная дама пожимает вам руку и представляется с натянутой улыбкой. «Нам нужны такие люди, как вы, в финансовом отделе, я думаю, вы обнаружите, что у нас репутация «любителей веселья» в компании!» Она все еще жмет тебе руку. Из-за неловкости вы ловите себя на том, что отвечаете: «Конечно, я заскочу».

"Большой! Мы постоянно приглашаем членов нашей команды на эксклюзивные встречи и мероприятия. На самом деле, у нас есть один на подходе!»

Она протягивает вам яркий флаер, украшенный статуэтками тики. «Я знаю, о чем вы думаете, — продолжает она, — больше бумаги. Но помните, вы по-прежнему получаете все основные привилегии работы в компании. Я слышал, что у Босса есть красивый степлер».

Джон мельком видит ваше приглашение. «Подождите… вы присоединились к Финансам? Они что-то празднуют? Могу ли я прийти?"

jon.getInvite(); // 'jon.getInvite() is not a function'

Извини, Джон, тебе Employee, но не TeamMember. Джону помогают убрать документы и получить доступ к stapler(), но это все! Вы обапотомки Employee.prototype, но только вытакже являетесь потомком TeamMember.prototype.

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

Краткое примечание

«…Но почему я не могу просто раздать всем чертов степлер?!»

Некоторые люди будут порицать ООП в JavaScript именно потому, что class — это просто функция-конструктор и некоторые методы его прототипа (не настоящий чертеж, который может быть в других языках), другие потому, что this сразу означает, что контекст должен поддерживаться, третьи потому что им больше подходит функциональное программирование и примеси (когда будете готовы, у меня есть статья на эту тему!). Однако если у вас есть 50 методов, к которым необходимо получить доступ для 1000 объектов, разница между 50 и 50 000 функций в памяти может повлиять на производительность. В любом случае, вы, скорее всего, увидите prototype и/или class в дикой природе.

В конце концов, некоторые из них вы уже использовали…

const numArray = new Array(4, 2, 1, 3);

numArray.length; // 4

numArray.sort(); // [1, 2, 3, 4]

Теперь вы знаете, почему MDN называет его Array.prototype.sort()!