Базовые шаблоны в JavaScript - Блог ITVDN
ITVDN: курсы программирования
Видеокурсы по
программированию
РУС
  • РУС
  • УКР

    Выбери свою IT специальность

    Подписка
    РУС
    • РУС
    • УКР
    Arrow
    🌷Набор групп на обучение с ментором - FrontEnd, .NET, Python, Java, FullStack, QA.
    Arrow

    Базовые шаблоны в JavaScript

    advertisement advertisement

    Прежде всего стоит освежить память и немного повторить основы.

    JavaScript – объектно-ориентированный язык программирования. Чаще всего в сценариях JS вы будете встречать объекты.

    Элементарные типы данных JS:

    • числа
    • строки
    • булевые(true/false)
    • null
    • undefined

    Объект в JS – это коллекция пар ключ/значение. Если же свойством объекта выступает функция, это свойство называют – методом.

    Разновидности объектов в JS :

    1. Собственные объекты:
    • встроенные (Array, Date)
    • пользовательские (var b = {};)

         2. Объекты окружения:

    • window
    • объекты DOM

    Прототип:

    Для использования наследования обычно применяют прототип.

    Что такое прототип – это объект. Каждая создаваемая функция получает свойство prototype, который ссылается на новый пустой объект.

    Что такое Шаблон :

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

    Что делают шаблоны:

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

    Типы шаблонов:

    • шаблоны проектирования
    • шаблоны кодирования
    • антишаблоны

    Рассмотрим основные приемы написания качественного кода на JS.

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

    • удобочитаемость (вы или человек, который будет после вас читать код, должен легко и быстро его понимать)
    • документация (опять же, для понимания написаного вами кода)
    • предсказуемость (опять же, вытекает из первого)
    • непротиворечивость (отдельные составляющие программы не должны противоречить друг другу)

    Первый прием(шаблон) на пути написания качественного кода  – сведение к минимуму количества глобальных переменных.

    Стараемся объявлять переменные в теле функций(так как мы помним, что функция есть локальной областью видимости). Любая переменная, объявляемая не в теле другой функции, является свойством глобального объекта window.

    Глобальный объект

    Почемy же нам стоит избегать глобальных переменных ? Они доступны всему приложению, соответсвенно, могут конфликтовать/перезаписываться.

    Решение – использование слова var при объявлении переменных. 

    function mult(x, y) {

        //антишаблон - глобальная переменная

        res = x * y;

        return res;

    };

    function mult(x, y) {

        //локальная переменная

        var res = x * y;

        return res;

    };

    function antiPat() {

        // антишаблон - использование нескольких операций присваивания

        // переменная res - локальна, переменная glob - глобальна

        // потому как присваивание выполняется справа налево

        // glob = 5 - в данном случае необъявленная переменная

        // операция эквивалентна var res = ( glob = 5 );

        var res = glob = 5;

    };

    function antiPat() {

        //решение : зарание объявить переменные;

        var res, glob;

        res = glob = 5;

    };

    Также переменные, объявленные с помощью слова var, не могут быть удалены, используя оператор delete.

    var global0 = 5;

    global1 = 10;                            // антишаблон

    (function () { global_inFunc = 15 }());         // антишаблон

    //пытаемся удалить

    delete global0;                                 // false

    delete global1;                                 // true

    delete global_inFunc;                           // true

    //проверяем

    typeof global0                                  // 'number'

    typeof global1                                  // 'undefined'

    typeof global_inFunc                     // 'undefined'

    В строгом режиме ('use strict';) присвоение значения необъявленной переменной вызовет ошибку.

    Глобальный объект

    var global = (function () { return this }());

    Получаем доступ к глобальному объекту, потому как ссылка this указывает на глобальный объект.

    Единственная инструкция var

    function func () {

        var x = 5, y = 10, mult = x * y, someObj = {}, k, l, m;

        return

    };

    У такого приема есть ряд приимуществ:

    • легко найти переменную(они все в одном месте)
    • уменьшает количество логических ошибок
    • уменьшает количество глобальных переменных(так как мы их объявили локально уже)
    • повышает удобочитаемость кода

    Подъем

    //антишаблон

    some = 'global';                  //глобальная переменная

    function example() {

        alert(some);           //undefined

        var some = 'local';

        alert(some);           //'local'

    };

    example();

    Почему так происходит? Потому что в JS интерпретатор проходит по областям видимости на первом этапе обработки кода и собирает объявление переменных фунций и формальных параметров. В локальной области видимости переменная some неопределена (undefined). Она существует как глобальная переменная и как локальная.

    Такое поведение именуется подъем (hoisting).

    Второй этап выполнения кода интерпретатором – создание функций-выражений и необъявленных переменных.

    Циклы for

    function func (){

        var i,  max, sampleArray;

        for ( i = 0; max = sampleArray.length; i < max; i++ ) {

            //    произвести действия над sampleArray[i]

        }

    };

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

    var i, sampleArray = [];

    for (i = sampleArray.length; i--;) {

        //    произвести действия над sampleArray[i]

    };

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

    var sampleArray = [],i = sampleArray.length;

    while(i--){ //    произвести действия над sampleArray[i]};

    Такие изменения будут ощутимы на участках приложения, где необходима максимальная производительность.

    Циклы for-in

    Циклы for-in используются для обхода объектов (не массивов – это возможно, но не рекоменуется).

    var car = {

        doors: 4,

        wheels: 4,

        engine: 1

    };

    // расширяем функционал

    // добавляем ко всем объектам метод ride

    if (typeof Object.prototype.ride === 'undefined') {

        Object.prototype.ride = function () { };

    };

    // Теперь все объекты через прототип имеют доступ к методу ride()

    // чтобы отбросить метод при перечислении свойств необходим

    // метод hasOwnProperty() для того, чтобы отфильтровать свойства прототипа

    var i, hasOwn = Object.prototype.hasOwnProperty;

    for (i in car) if (hasOwn.call(car, i)) {

        console.log(i, ' : ', car[i]);

    };

    Для каждого собственного свойства объекта выполнить кусок кода в фигурных скобках.

    Расширение prototype

    Данный шаблон следует использовать очень аккуратно.

    Даже если вы предупреждаете свою команду в докумментации (что является более предпочтительным и для новой комманды) или устно (недопустимо).

    If ( typeof Object.prototype.someMethod !== 'function' ) {

        Object.prototype.someMethod = function () {

            //do something...

        };

    };

    Приведение типов

    // шаблон

    var number = 0;

    if (number === false) {

        // не выполнится потому как number это 0, а не false

    };

    // антишаблон

    if (number == false){ // инструкция выполнится };

    Во избежание двузначности старайтесь использовать однозначную трактовку кода.

    Шаблоны eval(), setInterval(), setTimeout()

    Старайтесь не использовать в своих сценариях eval().

    Функция принимает строку и выполняет её как програмный код. А это уже ставит под удар безопасность приложение, так как eval() выполнит код хакера. Возможно, эта функция понадобится вам во время динамической генерации кода, тогда лучше заменить eval(), как пок­азано ниже:

    // антишаблон

    var property = 'name';

    alert(eval('obj.' + property));

    // лучше заменить на

    var property = 'name';

    alert(obj[property]);

    Функциям setInterval(), setTimeout() и конструктору  Function() старайтесь не передавать в качестве аргумента строки. По тем же причинам , что и функция eval().

    // антишаблон

    setTimeout( 'someFunc()', 5000);

    setTimeout( 'someFunc(1, 2, 3)', 5000);

    // заменить на

    setTimeout( someFunc(), 5000 );

    setTimeout( function(){ someFunc(1, 2, 3); }, 5000);

    Если по каким-либо причинам вам все-таки приходится применять функцию eval(), оберните её в самовызывающуюся функцию, этот шаблон поможет вам создать локальную область видимости, предотвратит перетирание переменных и предотвратит создание глобальных переменных.

    Также конструктор Function() отличается от  eval() тем, что ему доступна лишь глобальная область видимости.

    (function () {

        var local = 1;

        eval('local = 3; console.log(local)');      // результат 3

        console.log(local);                         // результат 3

    }());

    (function () {

        var local = 1;

        Function('console.log(typeof local);')();// результат undefined

    }());

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

    Одно из самых главных приоритетов при написании кода- это простота. Как говорится в знаменитой пословице: “Все гениальное просто.”

    На этом пока все. Желаю всем красивого кода. Всем спасибо!

    КОММЕНТАРИИ И ОБСУЖДЕНИЯ
    advertisement advertisement

    Покупай подпискус доступом ко всем курсам и сервисам

    Библиотека современных IT знаний в удобном формате

    Выбирай свой вариант подписки в зависимости от задач, стоящих перед тобой. Но если нужно пройти полное обучение с нуля до уровня специалиста, то лучше выбирать Базовый или Премиум. А для того чтобы изучить 2-3 новые технологии, или повторить знания, готовясь к собеседованию, подойдет Пакет Стартовый.

    Стартовый
    • Все видеокурсы на 3 месяца
    • Тестирование по 10 курсам
    • Проверка 5 домашних заданий
    • Консультация с тренером 30 мин
    59.99 $
    Оформить подписку
    Базовый
    • Все видеокурсы на 6 месяцев
    • Тестирование по 16 курсам
    • Проверка 10 домашних заданий
    • Консультация с тренером 60 мин
    89.99 $
    Оформить подписку
    Премиум
    • Все видеокурсы на 1 год
    • Тестирование по 24 курсам
    • Проверка 20 домашних заданий
    • Консультация с тренером 120 мин
    169.99 $
    Оформить подписку
    Notification success