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

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

}());

 

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

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

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