ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Categories:

JavaScipt: пример создания полифила

Продолжаю читать учебник по JavaScript:
https://learn.javascript.ru

В подразделе 8.3 «Встроенные прототипы» учебника приводится простой пример создания полифила, на котором можно четче понять, что такое «полифилы» и зачем они нужны. Вообще, про полифилы в учебнике уже рассказывалось ранее в подразделе 3.6 «Полифилы», но там не излагалось, как полифилы реализуют, потому что на тот момент ученик еще не получил достаточных для этого знаний. Если коротко, то полифил — это ручная реализация новой возможности языка, которую еще пока не успели реализовать разработчики браузера (если язык JavaScript используется в браузерной среде).

Итак, вот этот пример:
if (!String.prototype.repeat) {             // если такого метода нет,
                                            // добавляем его в прототип
    String.prototype.repeat = function(n) {
        return new Array(n + 1).join(this); // повторить строку n раз
    };
}

// проверка работы метода
alert( "La".repeat(3) ); // LaLaLa

Здесь String — это встроенная функция-конструктор для строк. Про функции-конструкторы рассказывалось в подразделе 4.5 «Конструкторы, создание объектов через "new"» учебника. Свойство prototype функции-конструктора String указывает на объект-прототип, который станет прототипом нового объекта, создаваемого функцией-конструктором String. Это один из методов реализации наследования в языке JavaScript. О наследовании рассказывается в разделе 8 «Прототипы, наследование» учебника.

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

Метод repeat для строк, конечно, описан в спецификации языка JavaScript:

https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/repeat

Но мы предполагаем, что в каких-то старых версиях браузеров этот метод может быть не реализован, а в текстах наших программ этот метод, предположим, активно используется. Конечно, можно найти в программах все использования метода repeat и как-то заменить его. Но мы идем другим путем и сами вручную пишем этот метод и добавляем его в объект-прототип всех строк, если его там нет. Это и происходит в вышеприведенном коде примера.

На этом часть статьи по поводу реализации полифила заканчиваю, а далее хотел бы разобрать, что это за функция repeat и каким образом она здесь реализована.

Вообще, функция repeat должна возвратить повторение заданной строки n раз (то есть возвращается тоже одна строка). Например, задана строка «La» и ее нужно повторить 3 раза, тогда возвращена должна быть строка «LaLaLa». Выделим реализацию метода repeat из вышеприведенного кода:
String.prototype.repeat = function(n) {
    return new Array(n + 1).join(this); // повторить строку n раз
};

Я сразу не смог понять, как работает этот код, поэтому стал разбирать по частям.

Я бы реализовал требуемое циклом, но в вышеприведенном коде нет цикла или рекурсии. Функция возвращает (с помощью служебного слова return) результат выражения new Array(n + 1).join(this).

Здесь Array — встроенная функция-конструктор для создания массивов. С помощью служебного слова new, примененного с функцией-конструктором Array, создается новый массив. В этом массиве не создается элементов, но длина массива становится равной n + 1. То есть обращение к значениям элементов такого массива возвратит специальное значение undefined (что по-русски означает «значение не определено» или «значение отсутствует»). Об этом рассказывалось в подразделе 5.4 «Массивы» учебника:

https://learn.javascript.ru/array#new-array
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Array

Далее к созданному массиву применяется метод join, который соединяет элементы массива в одну строку и возвращает эту строку. Про этот метод было рассказано в подразделе 5.5 «Методы массивов»:

https://learn.javascript.ru/array-methods#split-i-join

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

alert( "La".repeat(3) ); // LaLaLa

Внутри метода repeat встроенная переменная this становится равной строке «La».

Учитывая всё вышеизложенное, в итоге, как я думал, метод repeat должен был возвратить такую строку:

undefinedLaundefinedLaundefinedLaundefined

То есть, как я думал, должны были быть возвращены четыре (n + 1) значения элементов нового массива, каждый из которых равен специальному значению undefined, соединенные строкой «La». Но возвращается строка «LaLaLa». Почему всё работает правильно?

А дело в том, что метод join преобразует элементы массива со значением undefined или null в пустую строку. Об этом не было рассказано в учебнике, но об этом сказано в спецификации языка JavaScript:

https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/join
Tags: Образование, Программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments