Тематический план

  • 2.1 Веб-сервер и его использования




     Использование веб-сервера

    Понятие «веб-сервер» может относиться как к аппаратной начинке, так и к программному обеспечению. Или даже к обеим частям, работающим совместно.

    1. С точки зрения "железа", «веб-сервер» — это компьютер, который хранит файлы сайта (HTML-документы, CSS-стили, JavaScript-файлы, картинки и другие) и доставляет их на устройство конечного пользователя (веб-браузер и т.д.). Он подключен к сети Интернет и может быть доступен через доменное имя, подобное google.com.
    2. С точки зрения ПО, веб-сервер включает в себя несколько компонентов, которые контролируют доступ веб-пользователей к размещенным на сервере файлам, как минимум — это HTTP-серверHTTP-сервер — это часть ПО, которая понимает URL’ы (веб-адреса) и HTTP (протокол, который ваш браузер использует для просмотра веб-страниц).

    На самом базовом уровне, когда браузеру нужен файл, размещенный на веб-сервере, браузер запрашивает его через HTTP-протокол. Когда запрос достигает нужного веб-сервера ("железо"), сервер HTTP (ПО) принимает запрос, находит запрашиваемый документ (если нет, то сообщает об ошибке 404) и отправляет обратно, также через HTTP.




    Чтобы опубликовать веб-сайт, необходим либо статический, либо динамический веб-сервер.


     Статический веб-сервер

    Статический веб-сервер, или стек, состоит из компьютера ("железо") с сервером HTTP (ПО). Мы называем это «статикой», потому что сервер посылает размещенные файлы в браузер «как есть».


     Динамический веб-сервер

    Динамический веб-сервер состоит из статического веб-сервера и дополнительного программного обеспечения, чаще всего  сервера приложения и базы данных. Мы называем его «динамическим», потому что сервер приложений изменяет исходные файлы перед отправкой в ваш браузер по HTTP.

    Например, для получения итоговой страницы, которую вы просматриваете в браузере, сервер приложений может заполнить HTML-шаблон данными из базы данных. Такие сайты, как MDN или Википедия, состоят из тысяч веб-страниц, но они не являются реальными HTML документами — лишь несколько HTML-шаблонов и гигантские базы данных. Эта структура упрощает и ускоряет сопровождение веб-приложений и доставку контента.

    Прежде всего, веб-сервер должен содержать файлы веб-сайта, а именно все HTML-документы и связанные с ними ресурсы, включая изображения, CSS-стили, JavaScript-файлы, шрифты и видео.

    Технически, вы можете разместить все эти файлы на своем компьютере, но гораздо удобнее хранить их на выделенном веб-сервере, который:

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

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





  • 2.2 Переменные и типы данных



    JavaScript-приложению обычно нужно работать с информацией. Например:

    Интернет-магазин – информация может включать продаваемые товары и корзину покупок.

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

    Переменные используются для хранения этой информации.


     Переменная

    Переменная – это «именованное хранилище» для данных. Мы можем использовать переменные для хранения товаров, посетителей и других данных.

    Для создания переменной в JavaScript используйте ключевое слово let.

    Приведённая ниже инструкция создаёт (другими словами: объявляет или определяет) переменную с именем «message»:



    Теперь можно поместить в неё данные, используя оператор присваивания =:



    Строка сохраняется в области памяти, связанной с переменной. Мы можем получить к ней доступ, используя имя переменной:



    Для краткости можно совместить объявление переменной и запись данных в одну строку:



    Мы также можем объявить несколько переменных в одной строке:



    Многострочный вариант немного длиннее, но легче для чтения:




    Переменные и типы данных JavaScript

    В старых скриптах вы также можете найти другое ключевое слово: var вместо let:


    Ключевое слово var – почти то же самое, что и let. Оно объявляет переменную, но немного по-другому, «устаревшим» способом.

    Регистр имеет значение

    Переменные с именами apple и AppLE – это две разные переменные.

    Нелатинские буквы разрешены, но не рекомендуются

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



    Технически здесь нет ошибки, такие имена разрешены, но есть международная традиция использовать английский язык в именах переменных. Даже если мы пишем небольшой скрипт, у него может быть долгая жизнь впереди. Людям из других стран, возможно, придётся прочесть его не один раз.


     Константы

    Чтобы объявить константную, то есть, неизменяемую переменную, используйте const вместо let:



    Переменные, объявленные с помощью const, называются «константами». Их нельзя изменить. Попытка сделать это приведёт к ошибке:




     Придумывайте правильные имена

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

    Название переменной должно иметь ясный и понятный смысл, говорить о том, какие данные в ней хранятся.

    Именование переменных – это один из самых важных и сложных навыков в программировании. Быстрый взгляд на имена переменных может показать, какой код был написан новичком, а какой – опытным разработчиком.

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

    Пожалуйста, потратьте время на обдумывание правильного имени переменной перед её объявлением. Несколько хороших правил:

    • Используйте легко читаемые имена, такие как userName или shoppingCart.
    • Избегайте использования аббревиатур или коротких имён, таких как a, b, c, за исключением тех случаев, когда вы точно знаете, что так нужно.
    • Делайте имена максимально описательными и лаконичными. Примеры плохих имён: data и value. Такие имена ничего не говорят. Их можно использовать только в том случае, если из контекста кода очевидно, какие данные хранит переменная.
    • Договоритесь с вашей командой об используемых терминах. Если посетитель сайта называется «user», тогда мы должны называть связанные с ним переменные currentUser или newUser, а не, к примеру, currentVisitor или newManInTown.


     Типы данных

    JavaScript является слабо типизированным или динамическим языком. Это значит, что вам не нужно определять тип переменной заранее. Тип определится автоматически во время выполнения программы. Также это значит, что вы можете использовать одну переменную для хранения данных различных типов:


    let foo = 42; // сейчас foo типа Number

    foo = "bar"; // а теперь foo типа String

    foo = true; // foo становится типа Boolean

     

    Стандарт ECMAScript определяет 9 типов:

    • 6 типов данных являющихся примитивами:

    1. Undefined (Неопределенный тип)  : typeof instance === "undefined"
    2. Boolean (Булев, Логический тип) : typeof instance === "boolean"
    3. Number (Число) : typeof instance === "number"
    4. String (Строка) : typeof instance === "string"
    5. BigInt  : typeof instance === "bigint"
    6. Symbol (в ECMAScript 6)  : typeof instance === "symbol"

    • Null (Null тип ) : typeof instance === "object". Специальный примитив, используемый не только для данных но и в качестве указателя на финальную точку в Цепочке Прототипов;
    • Object ( Объект) : typeof instance === "object". Простая структура, используемая не только для хранения данных, но и для создания других структур, где любая структура создаётся с использованием ключевого слова new: new Object, new Array, new Map, new Set, new WeakMap, new WeakSet, new Date и множество других структур;
    • и Function : typeof instance === "function". Специальный случай, упрощающий определение типа для Функций, несмотря на то, что все функции конструктивно унаследованы от Object.

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





  • 2.3 Операторы JavaScript



     Операторы JavaScript

    В JavaScript можно выделить следующие виды операторов:

    • математические;
    • присваивания;
    • сравнения;
    • строковые;
    • условные;
    • логические.


     Математические операторы

    В JavaScript выделяют следующие математические операторы: + (сложение, унарный плюс), - (вычитание, отрицание), * (умножение), / (деление), % (остаток от деления), ** (возведение в степень), ++ (увеличение значения на 1), -- (уменьшение значения на 1).


    8 + 4; // 12 (результат сложения)

    8 - 4; // 4  (результат вычитания)

    8 * 4; // 32 (результат умножения)

    8 / 4; // 2  (результат деления)

    8 % 4; // 0  (результат вычисления остатка от деления)

    2 ** 3; // 8  (результат возведения числа 2 в степень 3)

    ++7;    // 8  (увеличение числа 7 на 1)

    --8;    // 7  (уменьшение числа 8 на 1)


    В результате выполнения математической операции всегда возвращается числовое значение.


    5 – 15;      // -10 (1 пример)
    '5' - '15';  // -10 (2 пример)

    JavaScript – это язык с динамическим приведением типов. Во втором примере оператор минус (–) является математическим и может оперировать только с числами. Для выполнения этой операции JavaScript приведёт значения первого и второго операнда к числам (5 и 15), а затем уже выполнит вычитание.

    Ещё один пример с использованием оператора минус (-):


    5 - 'px'; // NaN

    В этом примере JavaScript приведёт строку «px» к специальному числовому значению NaN. В результате вычисления 5 – NaN будет возвращён результат NaN.

    Пример с использованием оператора плюс (+):


    5 + 'px';  // "5px"

     

    Оператор плюс (+) не только математический, он также используется для конкатенации (соединения) строк.

    Выбор операции при использовании оператора плюс (+) зависит от типа значений операндов. Если хотя бы один из операндов является строкой, то данная операция рассматривается как операция конкатенации строк. В противном случае она будет считаться математической.

    В этом примере второй операнд является строкой, следовательно, данная операция будет операцией конкатенацией строк. Т.к. первый операндов не является строкой, то JavaScript приведёт его к ней. В результате будет возвращена строка «5px».

    Ещё оператор плюс (+) может применяться к одному операнду:

     

    +5.8;      // 5.8 (при применении к числу унарный оператор + ничего не изменяет)
    +'5.8';    // 5.8 (при применении унарного оператора + к не числовому значению приводит его к числу)
    +'5.8px';  // NaN (привёл текст к числовому значению NaN)

     

    Унарный оператор плюс (+) в основном используется для явного преобразования не числовых типов данных к числам.

    Оператор минус (–), также как и оператор плюс (+) может применяться к одному операнду. Если операнд является числом, то он просто изменит его знак на противоположный. В противном случае, он преобразует значение операнда к числу, а затем изменит его знак на противоположный.


    5 + (-10); //-5;
    -(-15);    // 15
    -'5';      // -5
    -'5px';    // NaN

    Операторы инкремента (++) и декремента (--) имеют префиксную и постфиксную форму.


    var num1, num2;
    num1 = 5;
    num2 = num1++; // постфиксная форма, т.е. сначала возвращается значение, а затем увеличивается 
    num2 = ++num1; // префиксная форма, т.е. сначала увеличивается значение переменной num1 на 1, а затем возвращается её значение

     

    Оператор процент (%) вычисляет остаток от деления первого операнда на второй:


    100 % 3; // 1

    Как вычисляется остаток от деления показано на картинке:



     Операторы присваивания

    Оператор равно (=) используется для присвоения (установления) левому операнду (переменной) значение правого операнда.


    num = 33;     // присвоим переменной num число 33
    num1 = num2;  // присвоим переменной num1 значение переменной num2

     

    В JavaScript имеются ещё составные операторы присваивания: +=, -=, *=, /=, %=, **=, <<=, >>=, >>>=, &=, ^=, |=. Данные операторы выполняют перед присваиванием ещё одну операцию.

    Эти операторы являются просто сокращением следующей записи:


    var x = 7;
    x += 8;   // 15
    x += '3'; // "153"
    x -= 30;  // 123
    x **= 2;  // 15129

     

     Операторы сравнения

    Операторы сравнения предназначены для сравнения двух операндов. Если сравнение верное, то в качестве результата этой операции возвращается true. В противном случае, значение false.

    В JavaScript выделяют следующие операторы сравнения: == (равенство), != (не равенство), === (строгое равенство), !== (строгое не равенство), > (больше), >= (больше или равно), < (меньше), <= (меньше или равно).


    // СРАВНЕНИЕ ЧИСЕЛ
    5 > 10;        // true
    5 === 2 + 3;   // true
    7 < 2 * 3;     // false
    4 <= 4;        // true
    +0 === -0;     // true
    // СРАВНЕНИЕ БУЛЕВЫХ ЗНАЧЕНИЙ
    true > false;  // true
    true == false; // false
    // РАВЕНСТВО null и undefined
    null == undefined; // true (особенность языка)

     

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

    При этом какой символ больше другого определяется по их кодам в таблице Unicode.


    // ПРИМЕР 1
    // 51 - код символа '3' // '3'.charCodeAt(0)
    // 50 - код символа '2' // '2'.charCodeAt(0)
    '3' > '25'; // true, т.к. 51 > 50

    // ПРИМЕР 2
    // 1080 - код символа 'и' // 'и'.charCodeAt(0)
    // 1090 - код символа 'т' // 'т'.charCodeAt(0)
    'символ' > 'строка'; // false, т.к. 1080 не больше 1090
     
    // ПРИМЕР 3
    'домик' > 'дом'; // true, т.к. у него больше символов

     

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


    // 1044 - код символа 'Д' // 'Д'.charCodeAt(0)
    // 1076 - код символа 'д' // 'д'.charCodeAt(0)
    'Дом' === 'дом'; // false, т.к. 'Д' не равно 'д'

    'Дом'.toLowerCase() === 'дом'.toLowerCase(); // true

    Если оба операнда являются объектами, то сравниваются их ссылки.


    var
      obj1 = {
        num: 3
      },
      obj2 = {
        num: 3
      },
      obj3 = obj1;
      
    obj1 == obj2;   // false, т.к. переменные имеют разные ссылки
    obj1 == obj3;   // true, т.к. переменные ссылаются на один и тотже объект
    obj1 === obj3;  // true, т.к. переменные ссылаются на один и тотже объект


    Во всех операциях, кроме операций с использованием строго равенства и строго не равенства, JavaScript перед операцией сравнения приводит их к одному типу. Данное действие он конечно же выполняет только в том случае, если операнды имеют разный тип данных.

    Если операнды имеют примитивный тип данных, то они приводится при операции сравнения к числу:


    '2' == 2;    // true, т.к. строка '2' будет приведена к числу 2
    true != 0;   // true, т.к. true будет приведено к 1
    false == 0;  // true, т.к. false == true
    '' > -5;     // true, т.к. пустая строка будет приведена к 0
    '' == false; // true, т.к. пустая строка будет приведена к 0 и false тоже к 0
    '5px' == 5;  // false, т.к. строка '5px' будет приведена к NaN

     

    При сравнении объекта с примитивным типом данных, JavaScript вызывает его метод valueOf или toString. Полученное значение, если оно не объект, сравнивается с примитивным типом данных и возвращается результат. Если метод valueOf или toString, то выбрасывается ошибка «Cannot convert object to primitive value».


    // ПРИМЕР 1
    var obj = {
      num: 5,
      toString: function () {
        return this.num;
      }
    };
    obj == 5; // true
     
    // ПРИМЕР 2
    var 
      arr = [4, 5, 6],
      str = '4,5,6';
    arr == str; // true

     

    В большинстве случаев при выполнении операций равенства или не равенства, их желательно выполнять с использованием операторов === и !==. Применение данных операторов позволит исключить неожиданные ситуации при сравнении операндов с различным типом данных.


    2 === '2';  // false, т.к. тип данных разный
    true === 1; // false, т.к. тип данных разный

     

     Строковые операторы

    Для выполнения операций со строками в JavaScript нет никаких специальных операторов.

    Для конкатенации (соединения) строк используется оператор плюс (+). Данный оператор применяется не только для соединения строк, но также и для сложения чисел. Кроме этого, данный оператор может использоваться с одним операндом. Этот вариант применение оператора, в основном используется тогда, когда нужно некоторое значение привести к числу.


    "одна строка " + "другая строка"; // "одна строка другая строка" (использование оператора + для сложения строк)
    7 + 8; // 15 (использование оператора + для сложения чисел)
    +"7"; // 7 (использование оператора + для приведения строки к числу)

     

    Для сравнения строк используются операторы строго равенства (===), больше (>), меньше (<) и др. Т.е. точно такие же операторы которые используются для сравнения чисел, объектов и других типов данных.


    var str = "некоторый текст";
    str === "некоторый текст"; // true

     

     Побитовые операторы

    Побитовые операторы предназначены для выполнения логических операций над целыми числами, а точнее над их двоичными представлениями.

    Представление числа в двоичной системе осуществляется посредством 32 битов.


    // 5  => 0000 0000 0000 0000 0000 0000 0000 0101
    // 10 => 0000 0000 0000 0000 0000 0000 0000 1010

     

    В JavaScript имеются следующие побитовые операторы: & (побитовое И), | (побитовое ИЛИ), ~ (побитовое НЕ), ^ (исключающее ИЛИ), << (сдвиг влево), >> (сдвиг вправо), >>> (сдвиг вправо с заполнением нулями).

    Пример с использованием оператора &:


    // ПРИМЕР 1
    5 & 10; // 0
    // 5      => ... 0000 0101
    // 10     => ... 0000 1010
    // 5 & 10 => ... 0000 0000
    // 02 = 010
     
    // ПРИМЕР 2
    5 & 7; // 5
    // 5      => ... 0000 0101
    // 7      => ... 0000 0111
    // 5 & 7  => ... 0000 0101
    // 1012 = 510
     
    // выполнение логической операции «И» осуществляется для каждой пары битов, находящихся на одинаковых позициях в двоичных представлениях операндов
    // логическое "И" работает так: 0 & 0 = 0, 1 & 0 = 0, 0 & 1 = 0, 1 & 1 = 1.

     

    Пример с использованием оператора |:


    // ПРИМЕР 1
    5 | 10; // 15
    // 5      => ... 0000 0101
    // 10     => ... 0000 1010
    // 5 | 10 => ... 0000 1111
    // 11112 = 1510
     
    // ПРИМЕР 2
    5 | 4; // 5
    // 5      => ... 0000 0101
    // 4      => ... 0000 0100
    // 5 | 4  => ... 0000 0101
    // 1012 = 510
     
    // выполнение логической операции «ИЛИ» осуществляется для каждой пары битов, находящихся на одинаковых позициях в двоичных представлениях операндов
    // логическое "ИЛИ" работает так: 0 | 0 = 0, 1 | 0 = 1, 0 | 1 = 1, 1 | 1 = 1.

     

    Примеры с использованием оператора ^:


    // ПРИМЕР 1
    5 ^ 7; // 2
    // 5      => ... 0000 0101
    // 7      => ... 0000 0111
    // 5 ^ 7  => ... 0000 0010
    // 102 = 210
     
    // ПРИМЕР 2
    5 ^ 4; // 1
    // 5      => ... 0000 0101
    // 4      => ... 0000 0100
    // 5 ^ 4  => ... 0000 0001
    // 12 = 110
     
    // выполнение логической операции «исключающее ИЛИ» осуществляется для каждой пары битов, находящихся на одинаковых позициях в двоичных представлениях операндов
    // исключающее "ИЛИ" работает так: 0 ^ 0 = 0, 1 ^ 0 = 1, 0 ^ 1 = 1, 1 ^ 1 = 0.

     

    Пример с использованием оператора ~:


    // ПРИМЕР 1
    ~5; // -6
    // 5       => 0000 0000 0000 0000 0000 0000 0000 0101
    // ~5 (-6) => 1111 1111 1111 1111 1111 1111 1111 1010
    // выполнение логической операции «НЕ» осуществляется для каждого бита двоичного представления операнда (число 0 заменяется на 1, а 1 на 0).

     

    Пример с использованием оператора <<:


    // ПРИМЕР 1
    5 << 3; // 40
    // 5      => 0000 0000 0000 0000 0000 0000 0000 0101
    // 5 << 3 => 0000 0000 0000 0000 0000 0000 0010 1000
    // 1010002 = 4010
     
    // operand1 << operand2
    // оператор << сдвигает двоичное представление operand1 на количество битов, указанных посредством второго операнда operand2, добавляя нули справа.

     

    Пример с использованием оператора >>:


    // ПРИМЕР 1
    45 >> 3; // 5
    // 45      => 0000 0000 0000 0000 0000 0000 0010 1101
    // 45 >> 3 => 0000 0000 0000 0000 0000 0000 0000 0101
    // 1012 = 510
     
    // operand1 >> operand2
    // оператор >> сдвигает двоичное представление operand1 на количество битов, указанных посредством второго операнда operand2; лишние биты, сдвинутые вправо, отбрасываются.

     

    Пример с использованием оператора >>>:


    // ПРИМЕР 1
    -30 >>> 3; // 536870908
    // -30       => 1111 1111 1111 1111 1111 1111 1110 0010
    // -30 >>> 3 => 0001 1111 1111 1111 1111 1111 1111 1100 
    // 111111111111111111111111111002 = 53687090810
     
    // operand1 >>> operand2
    // оператор >>> сдвигает двоичное представление operand1 на количество битов, указанных посредством второго операнда operand2; лишние биты, сдвинутые вправо, отбрасываются; число слево дополняется нулевыми битами.




  • 2.4 Циклы и их виды



     Циклы в JavaScript

    Циклы - простой способ сделать какое-то действие несколько раз.

    Существует множество различных видов циклов, но все они, по сути, делают тоже самое: повторяют какое-либо действие несколько раз (не забывайте про нулевой раз повторения, отсчёт в массиве начинается с 0). Различные по строению циклы предлагают разные способы для определения начала и окончания цикла. Для различных задач программирования существуют свои операторы цикла, с помощью которых они решаются намного проще.

    Операторы предназначенные для организации циклов в JavaScript:

    • Цикл_for
    • Цикл_do...while
    • Цикл_while
    • Метка_(label)
    • break
    • continue
    • for...in
    • for...of


     Цикл for

    Цикл for  повторяет действия, пока не произойдёт какое-либо специальное событие завершения цикла. Оператор for в JavaScript аналогичен оператору for в Java и C. Объявление оператора for выглядит следующим образом:

    for ([начало]; [условие]; [шаг]) выражения

    При его выполнении происходит следующее:

    1. Выполняется выражение начало, если оно указано. Это выражение обычно инициализирует один или несколько счётчиков, но синтаксис позволяет выражению быть любой сложности. Также используется для объявления переменных.
    2. Выполняется условие. Если условие истинно, то выполняются выражения. Если оно ложно, цикл for прерывается. Если же условие полностью пропущено, то оно считается истинным.
    3. Выполняются выражения. Чтобы выполнить несколько выражений, используются блок-выражение { ... }  для группировки выражений.
    4. Обновляется шаг, если он есть, а затем управление возвращается к шагу 2.


     Цикл do...while

    Цикл do...while повторяется пока заданное условие истинно. Оператор do...while имеет вид:


    do
      выражения
    while (условие);

    Выражения выполняются пока условие истинно. Чтобы использовать несколько выражений, используйте блок-выражение  { ... }, чтобы сгруппировать их. Если условие истинно, выражения выполнятся снова. В конце каждого прохода условие проверяется. Если условие ложно, выполнение приостанавливается и управление передаётся выражению после do...while.


     Цикл while

    Цикл while выполняет выражения пока условие истинно. Выглядит он так:


    while (условие)
      выражения


    Если условие становится ложным, выражения в цикле перестают выполняться и управление переходит к выражению после цикла.

    Условие проверяется на истинность до того, как выполняются выражения в цикле. Если условие истинно, выполняются выражения, а затем условие проверяется снова. Если условие ложно, выполнение приостанавливается и управление переходит к выражению после while.

    Чтобы использовать несколько выражений, используйте блок выражение {...}, чтобы сгруппировать их.


     Метка (label)

    Метка представляет собой оператор с индентификатором, который позволяет вам ссылаться на какое-то место в вашей программе. Например, вы можете использовать метку, чтобы обозначить цикл, а затем использовать операторы break или continue, чтобы указать, должна ли программа прерывать цикл или продолжать его выполнение.

    Синтаксис метки следующий:


    метка :
       оператор


    Например:

    markLoop:
    while (theMark == true) {
       doSomething();
    }


    В этом примере, метка markLoop обозначает цикл while.

    Значение метки может быть любым корректным JavaScript индентификатором, не являющимся зарезервированным словом. Оператор, указанный вами после метки может быть любым выражением.


     break

    Используйте оператор break, чтобы прерывать цикл, переключать управление или в сочетании с оператором метка.Когда вы используете break без метки, он прерывает циклы while, do-while и for или сразу переключает управление к следующему выражению.

    • Когда вы используете break с меткой, он прерывает специально отмеченное выражение.

    Синтаксис оператора может быть таким:

    1. break;
    2. break Метка;

    Первая форма синтаксиса прерывает цикл совсем или переключает управление; вторая прерывает специально обозначенное выражение.

     continue

    Оператор continue используется, чтобы шагнуть на шаг вперёд в циклах while, do-while, for или перейти к метке.

    • Когда вы используете continue без метки, он прерывает текущую итерацию циклов while, do-while и for и продолжает выполнение цикла со следующей итерации. В отличие от break, continue не прерывает выполнение цикла полностью. В цикле while он прыгает к условию. А в for увеличивает шаг.
    • Когда вы используете continue с меткой, он применяется к циклу с этой меткой.

    Синтаксис continue может выглядеть так:

    1. continue;
    2. continue Метка;


     for...in

    Оператор for...in проходит по всем перечисленным свойствам объекта. JavaScript выполнит указанные выражения для каждого отдельного свойства. Цикл for...in выглядит так:

    for (variable in object) {
      выражения
    }


     for...of

    Оператор for...of создаёт цикл, проходящий по перечисленным объектам (включая Array, Map, Set, объект arguments и так далее), вызывая на каждой итерации функцию с выражениями, которые надо выполнить для получения значения каждого отдельного свойства.

    for (variable of object) {
      выражения
    }


     Примеры

    for
    <form name="selectForm">
      <p>
        <label for="musicTypes">Выберите некоторые жанры музыки, а затем нажмите на кнопку ниже:</ label>
        <select id="musicTypes" name="musicTypes" multiple=" multiple ">
          <option selected="selected ">R&B</option>
          <option>Jazz</ option>
          <option>Blues </option>
          <option>New Age </option>
          <option>Classical </option>
          <option>Opera </option>
        </select>
      </p>
      <p><input id=" btn" type="button" value ="Как много выбрано?" /></p>
    </form>
     
    <script>
    function howMany(selectObject) {
      var numberSelected = 0;
      for (var i = 0; i < selectObject.options.length; i++) {
        if (selectObject.options [i].selected) {
          numberSelected++;
        }
      }
      return numberSelected;
    }
     
    var btn = document.getElementById("btn");
    btn.addEventListener("click", function(){
      alert('Выбрано элементов: ' + howMany (document.selectForm.musicTypes))
    });
    </script>

    do..while

    do {
      i += 1;
      console.log(i);
    } while (i < 5);

    while

    var n = 0;
    var x = 0;
    while (n < 3) {
      n++;
      x += n;
    }
     
    while (true) {
      console.log("Hello, world");
    }


    break

    for (i = 0 ; i < a.length; i ++) {
      if (a[i ] == theValue) {
        break;
      }
    }
    var x = 0;
    var z = 0
    labelCancelLoops: while ( true) {
      console.log("Внешний цикл: " + x);
      x += 1;
      z = 1;
      while (true) {
        console.log("Внутренний цикл: " + z);
        z += 1;
        if (z === 10 && x === 10 ) {
          break labelCancelLoops;
        } else if (z === 10) {
          break;
        }
      }
    }


    continue

    var i = 0;
    var n = 0;
    while (i < 5) {
      i++;
      if (i == 3) {
        continue;
      }
      n += i;
    }
    checkiandj:
      while (i < 4) {
        console.log(i);
        i += 1;
        checkj:
          while (j > 4) {
            console.log(j );
            j -= 1;
            if ((j % 2) != 0 ) {
              continue checkj;
            }
            console.log(j + " чётное.");
          }
          console.log("i = " + i);
          console.log("j = " + j);
      }


    for..in

    function dump_props(obj, obj_name ) {
      var result = "" ;
      for (var i in obj) {
        result += obj_name + "." + i + " = " + obj[i] + "<br>";
      }
      result += "<hr>";
      return result;
    }
    let obj = {model: 'AUDI A8', year: '2019', color: 'brown'}
     
    for (key in obj) {
      console.log(`${key} = ${obj[key]}`);
    }
    // model = AUDI A8
    // year = 2019
    // color = brown


    for..of

    let arr = [3, 5, 7];
    arr.foo = "hello" ;

    for ( let i in arr ) {
       console.log(i); // выводит "0", "1", "2", "foo"
    }
     
    for ( let i of arr) {
       console.log(i); // выводит "3", "5", "7"
    }




  • 2.5 Массивы данных



     Массивы данных JavaScript

    Объекты позволяют хранить данные со строковыми ключами. Это замечательно.

    Но довольно часто мы понимаем, что нам необходима упорядоченная коллекция данных, в которой присутствуют 1-й, 2-й, 3-й элементы и т.д. Например, она понадобится нам для хранения списка чего-либо: пользователей, товаров, элементов HTML и т.д.

    В этом случае использовать объект неудобно, так как он не предоставляет методов управления порядком элементов. Мы не можем вставить новое свойство «между» уже существующими. Объекты просто не предназначены для этих целей.

    Для хранения упорядоченных коллекций существует особая структура данных, которая называется массив, Array.


     Объявление

    Существует два варианта синтаксиса для создания пустого массива:


    let arr = new Array();

    let arr = [];


    Практически всегда используется второй вариант синтаксиса. В скобках мы можем указать начальные значения элементов:


    let fruits = ["Яблоко", "Апельсин", "Слива"];


    Элементы массива нумеруются, начиная с нуля.

    Мы можем получить элемент, указав его номер в квадратных скобках:


    let fruits = ["Яблоко", "Апельсин", "Слива"];

     

    alert( fruits[0] ); // Яблоко

    alert( fruits[1] ); // Апельсин

    alert( fruits[2] ); // Слива


    Мы можем заменить элемент:


    fruits[2] = 'Груша'; // теперь ["Яблоко", "Апельсин", "Груша"]


    …Или добавить новый к существующему массиву:


    fruits[3] = 'Лимон'; // теперь ["Яблоко", "Апельсин", "Груша", "Лимон"]


    Общее число элементов массива содержится в его свойстве length:


    let fruits = ["Яблоко", "Апельсин", "Слива"];

     

    alert( fruits.length ); // 3


    Вывести массив целиком можно при помощи a lert.


    let fruits = ["Яблоко", "Апельсин", "Слива"];

     

    alert( fruits ); // Яблоко, Апельсин, Слива


    В массиве могут храниться элементы любого типа.


    Например:

    // разные типы значений

    let arr = [ 'Яблоко', { name: 'Джон' }, true, function() { alert('привет'); } ];

     

    // получить элемент с индексом 1 (объект) и затем показать его свойство

    alert( arr[1].name ); // Джон

     

    // получить элемент с индексом 3 (функция) и выполнить её

    arr[3](); // привет


     Висячая запятая

    Список элементов массива, как и список свойств объекта, может оканчиваться запятой:


    let fruits = [

      "Яблоко",

      "Апельсин",

      "Слива",

    ];


    «Висячая запятая» упрощает процесс добавления/удаления элементов, так как все строки становятся идентичными.


     Методы pop/push, shift/unshift

    Очередь – один из самых распространённых вариантов применения массива. В области компьютерных наук так называется упорядоченная коллекция элементов, поддерживающая два вида операций:

    • push добавляет элемент в конец.
    • shift удаляет элемент в начале, сдвигая очередь, так что второй элемент становится первым.

    Массивы поддерживают обе операции.

    На практике необходимость в этом возникает очень часто. Например, очередь сообщений, которые надо показать на экране.

    Существует и другой вариант применения для массивов – структура данных, называемая стек.

    Она поддерживает два вида операций:

    • push добавляет элемент в конец.
    • pop удаляет последний элемент.

    Таким образом, новые элементы всегда добавляются или удаляются из «конца».

    Примером стека обычно служит колода карт: новые карты кладутся наверх и берутся тоже сверху:

    Массивы в JavaScript могут работать и как очередь, и как стек. Мы можем добавлять/удалять элементы как в начало, так и в конец массива.

    В компьютерных науках структура данных, делающая это возможным, называется двусторонняя очередь.


    Методы, работающие с концом массива:

     pop

    Удаляет последний элемент из массива и возвращает его:


    let fruits = ["Яблоко", "Апельсин", "Груша"];

     

    alert( fruits.pop() ); // удаляем "Груша" и выводим его

     

    alert( fruits ); // Яблоко, Апельсин


     push

    Добавляет элемент в конец массива:


    let fruits = ["Яблоко", "Апельсин"];

     

    fruits.push("Груша");

     

    alert( fruits ); // Яблоко, Апельсин, Груша

    Вызов fruits.push(...) равнозначен fruits[fruits.length] = ....


    Методы, работающие с началом массива:

     shift

    Удаляет из массива первый элемент и возвращает его:


    let fruits = ["Яблоко", "Апельсин", "Груша"];

     

    alert( fruits.shift() ); // удаляем Яблоко и выводим его

     

    alert( fruits ); // Апельсин, Груша


     unshift

    Добавляет элемент в начало массива:


    let fruits = ["Апельсин", "Груша"];

     

    fruits.unshift('Яблоко');

     

    alert( fruits ); // Яблоко, Апельсин, Груша


    Методы push и unshift могут добавлять сразу несколько элементов:


    let fruits = ["Яблоко"];

     

    fruits.push("Апельсин", "Груша");

    fruits.unshift("Ананас", "Лимон");

     

    // ["Ананас", "Лимон", "Яблоко", "Апельсин", "Груша"]

    alert( fruits );


     Внутреннее устройство массива

    Массив – это особый подвид объектов. Квадратные скобки, используемые для того, чтобы получить доступ к свойству arr[0] – это по сути обычный синтаксис доступа по ключу, как obj[key], где в роли obj у нас arr, а в качестве ключа – числовой индекс.

    Массивы расширяют объекты, так как предусматривают специальные методы для работы с упорядоченными коллекциями данных, а также свойство length. Но в основе всё равно лежит объект.

    Следует помнить, что в JavaScript существует 8 основных типов данных. Массив является объектом и, следовательно, ведёт себя как объект.

    Например, копируется по ссылке:


    let fruits = ["Банан"]

     

    let arr = fruits; // копируется по ссылке (две переменные ссылаются на один и тот же массив)

     

    alert( arr === fruits ); // true

     

    arr.push("Груша"); // массив меняется по ссылке

     

    alert( fruits ); // Банан, Груша - теперь два элемента


    …Но то, что действительно делает массивы особенными – это их внутреннее представление. Движок JavaScript старается хранить элементы массива в непрерывной области памяти, один за другим, так, как это показано на иллюстрациях к этой главе. Существуют и другие способы оптимизации, благодаря которым массивы работают очень быстро.

    Но все они утратят эффективность, если мы перестанем работать с массивом как с «упорядоченной коллекцией данных» и начнём использовать его как обычный объект.

    Например, технически мы можем сделать следующее:


    let fruits = []; // создаём массив

     

    fruits[99999] = 5; // создаём свойство с индексом, намного превышающим длину массива

     

    fruits.age = 25; // создаём свойство с произвольным именем


    Это возможно, потому что в основе массива лежит объект. Мы можем присвоить ему любые свойства.

    Но движок поймёт, что мы работаем с массивом, как с обычным объектом. Способы оптимизации, используемые для массивов, в этом случае не подходят, поэтому они будут отключены и никакой выгоды не принесут.

    Варианты неправильного применения массива:

    • Добавление нечислового свойства, например: arr.test = 5.
    • Создание «дыр», например: добавление arr[0], затем arr[1000] (между ними ничего нет).
    • Заполнение массива в обратном порядке, например: arr[1000], arr[999] и т.д.

    Массив следует считать особой структурой, позволяющей работать с упорядоченными данными. Для этого массивы предоставляют специальные методы. Массивы тщательно настроены в движках JavaScript для работы с однотипными упорядоченными данными, поэтому, пожалуйста, используйте их именно в таких случаях. Если вам нужны произвольные ключи, вполне возможно, лучше подойдёт обычный объект {}.


     Эффективность

    Методы push/pop выполняются быстро, а методы shift/unshift – медленно.

    Почему работать с концом массива быстрее, чем с его началом? Давайте посмотрим, что происходит во время выполнения:


    fruits.shift(); // удаляем первый элемент с начала


    Просто взять и удалить элемент с номером 0 недостаточно. Нужно также заново пронумеровать остальные элементы.

    Операция shift должна выполнить 3 действия:

    1. Удалить элемент с индексом 0.
    2. Сдвинуть все элементы влево, заново пронумеровать их, заменив 1 на 0, 2 на 1 и т.д.
    3. Обновить свойство length .

    Чем больше элементов содержит массив, тем больше времени потребуется для того, чтобы их переместить, больше операций с памятью.

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

    А что же с push/pop? Им не нужно ничего перемещать. Чтобы удалить элемент в конце массива, метод pop очищает индекс и уменьшает значение length.

    Действия при операции pop:


    fruits.pop(); // удаляем один элемент с конца


    Метод pop не требует перемещения, потому что остальные элементы остаются с теми же индексами. Именно поэтому он выполняется очень быстро.

    Аналогично работает метод push.


     Перебор элементов

    Одним из самых старых способов перебора элементов массива является цикл for по цифровым индексам:


    let arr = ["Яблоко", "Апельсин", "Груша"];

     

    for (let i = 0; i < arr.length; i++) {

      alert( arr[i] );

    }


    Но для массивов возможен и другой вариант цикла, for..of:


    let fruits = ["Яблоко", "Апельсин", "Слива"];

     

    // проходит по значениям

    for (let fruit of fruits) {

      alert( fruit );

    }


    Цикл for..of не предоставляет доступа к номеру текущего элемента, только к его значению, но в большинстве случаев этого достаточно. А также это короче.

    Технически, так как массив является объектом, можно использовать и вариант for..in:


    let arr = ["Яблоко", "Апельсин", "Груша"];

     

    for (let key in arr) {

      alert( arr[key] ); // Яблоко, Апельсин, Груша

    }


    Но на самом деле это – плохая идея. Существуют скрытые недостатки этого способа:

    1. Цикл for..in выполняет перебор всех свойств объекта, а не только цифровых.

    В браузере и других программных средах также существуют так называемые «псевдомассивы» – объекты, которые выглядят, как массив. То есть, у них есть свойство length и индексы, но они также могут иметь дополнительные нечисловые свойства и методы, которые нам обычно не нужны. Тем не менее, цикл for..in выведет и их. Поэтому, если нам приходится иметь дело с объектами, похожими на массив, такие «лишние» свойства могут стать проблемой.

    2. Цикл for..in оптимизирован под произвольные объекты, не массивы, и поэтому в 10-100 раз медленнее. Увеличение скорости выполнения может иметь значение только при возникновении узких мест. Но мы всё же должны представлять разницу.

    В общем, не следует использовать цикл for..in для массивов.


     Немного о «length»

    Свойство length автоматически обновляется при изменении массива. Если быть точными, это не количество элементов массива, а наибольший цифровой индекс плюс один.

    Например, единственный элемент, имеющий большой индекс, даёт большую длину:


    let fruits = [];

    fruits[123] = "Яблоко" ;

     

    alert( fruits.length ); // 124


    Обратите внимание, что обычно мы не используем массивы таким образом.

    Ещё один интересный факт о свойстве length – его можно перезаписать.

    Если мы вручную увеличим его, ничего интересного не произойдёт. Зато, если мы уменьшим его, массив станет короче. Этот процесс необратим, как мы можем понять из примера:


    let arr = [1, 2, 3, 4, 5];

     

    arr.length = 2; // укорачиваем до двух элементов

    alert( arr ); // [1, 2]

     

    arr.length = 5; // возвращаем length как было

    alert( arr[3] ); // undefined: значения не восстановились


    Таким образом, самый простой способ очистить массив – это arr.length = 0;.


     new Array()

    Существует ещё один вариант синтаксиса для создания массива:


    let arr = new Array("Яблоко" , "Груша", "и тд");


    Он редко применяется, так как квадратные скобки [] короче. Кроме того, у него есть хитрая особенность.

    Если new Array вызывается с одним аргументом, который представляет собой число, он создаёт массив без элементов, но с заданной длиной.

    Давайте посмотрим, как можно оказать себе медвежью услугу:


    let arr = new Array(2); // создастся ли массив [2]?

     

    alert( arr[0] ); // undefined! нет элементов.

     

    alert( arr.length ); // length 2


    Как мы видим, в коде, представленном выше, в new Array(number) все элементы равны undefined.

    Чтобы избежать появления таких неожиданных ситуаций, мы обычно используем квадратные скобки, если, конечно, не знаем точно, что по какой-то причине нужен именно Array.


     Многомерные массивы

    Массивы могут содержать элементы, которые тоже являются массивами. Это можно использовать для создания многомерных массивов, например, для хранения матриц:


    let matrix = [

      [1, 2, 3 ],

      [4, 5, 6 ],

      [7, 8, 9 ]

    ];

     

    alert( matrix[1][1] ); // 5, центральный элемент


     toString

    Массивы по-своему реализуют метод toString, который возвращает список элементов, разделённых запятыми.


    Например:

    let arr = [1, 2 , 3];

     

    alert( arr ); // 1,2,3

    alert( String(arr) === '1,2,3' ); // true


    Давайте теперь попробуем следующее:


    alert( [] + 1 ); // "1"

    alert( [1] + 1 ); // "11"

    alert( [1,2] + 1 ); // "1,21"


    Массивы не имеют ни Symbol.toPrimitive, ни функционирующего valueOf, они реализуют только преобразование toString, таким образом, здесь [] становится пустой строкой, [1] становится "1", а [1,2] становится "1,2".

    Когда бинарный оператор плюс "+" добавляет что-либо к строке, он тоже преобразует это в строку, таким образом:


    alert( "" + 1 ); // "1"

    alert( "1" + 1 ); // "11"

    alert( "1,2" + 1 ); // "1,21"


     Итого

    Массив – это особый тип объекта, предназначенный для работы с упорядоченным набором элементов.

    • Объявление:
    • // квадратные скобки (обычно)
    • let arr = [item1, item2...];

    • // new Array (очень редко)

       let arr = new Array(item1 , item2...);


    Вызов new Array(number) создаёт массив с заданной длиной, но без элементов.

    • Свойство length отражает длину массива или, если точнее, его последний цифровой индекс плюс один. Длина корректируется автоматически методами массива.
    • Если мы уменьшаем length вручную, массив укорачивается.

    Мы можем использовать массив как двустороннюю очередь, используя следующие операции:

    • push(...items)добавляет items в конец массива.
    • pop() удаляет элемент в конце массива и возвращает его.
    • shift() удаляет элемент в начале массива и возвращает его.
    • unshift(...items) добавляет items в начало массива.

    Чтобы пройтись по элементам массива:

    • for (let i=0; i<arr.length; i++) – работает быстрее всего, совместим со старыми браузерами.
    • for (let item of arr) – современный синтаксис только для значений элементов (к индексам нет доступа).
    • for (let i in arr) – никогда не используйте для массивов!





  • 2.6 Функции и применение





     Функции JavaScript

    Зачастую нам надо повторять одно и то же действие во многих частях программы.

    Например, необходимо красиво вывести сообщение при приветствии посетителя, при выходе посетителя с сайта, ещё где-нибудь.

    Чтобы не повторять один и тот же код во многих местах, придуманы функции. Функции являются основными «строительными блоками» программы.

    Примеры встроенных функций вы уже видели – это alert(message), prompt(message, default) и confirm(question). Но можно создавать и свои.


     Объявление функции

    Для создания функций мы можем использовать объявление функции.


    Пример объявления функции:

    function showMessage() {

      alert( 'Всем привет!' );

    }


    Вначале идёт ключевое слово function, после него имя функции, затем список параметров в круглых скобках через запятую (в вышеприведённом примере он пустой) и, наконец, код функции, также называемый «телом функции», внутри фигурных скобок.


    function имя(параметры) {

      ...тело...

    }


    Наша новая функция может быть вызвана по её имени: showMessage().


    Например:

    function showMessage() {

      alert( 'Всем привет!' );

    }


    showMessage();

    showMessage();


    Вызов showMessage() выполняет код функции. Здесь мы увидим сообщение дважды.

    Этот пример явно демонстрирует одно из главных предназначений функций: избавление от дублирования кода.

    Если понадобится поменять сообщение или способ его вывода – достаточно изменить его в одном месте: в функции, которая его выводит.


     Локальные переменные

    Переменные, объявленные внутри функции, видны только внутри этой функции.


    Например:

    function showMessage() {

      let message = "Привет, я JavaScript!"; // локальная переменная


      alert( message );

    }

     

    showMessage(); // Привет, я JavaScript!

     

    alert( message ); // <-- будет ошибка, т.к. переменная видна только внутри функции


     Внешние переменные

    У функции есть доступ к внешним переменным, например:


    let userName = 'Вася';

     

    function showMessage() {

      let message = 'Привет, ' + userName;

      alert(message);

    }

     

    showMessage(); // Привет, Вася


    Функция обладает полным доступом к внешним переменным и может изменять их значение.


    Например:

    let userName = 'Вася';

     

    function showMessage() {

      userName = "Петя"; // (1) изменяем значение внешней переменной

     

      let message = 'Привет, ' + userName ;

      alert(message);

    }

     

    alert( userName ); // Вася перед вызовом функции

     

    showMessage();

     

    alert( userName ); // Петя, значение внешней переменной было изменено функцией


    Внешняя переменная используется, только если внутри функции нет такой локальной.

    Если одноимённая переменная объявляется внутри функции, тогда она перекрывает внешнюю. Например, в коде ниже функция использует локальную переменную userName. Внешняя будет проигнорирована:


    let userName = 'Вася';

     

    function showMessage() {

      let userName = "Петя"; // объявляем локальную переменную

     

      let message = 'Привет, ' + userName ; // Петя

      alert(message);

    }

     

    // функция создаст и будет использовать свою собственную локальную переменную userName

    showMessage();

     

    alert( userName ); // Вася, не изменилась, функция не трогала внешнюю переменную


     Глобальные переменные

    Переменные, объявленные снаружи всех функций, такие как внешняя переменная userName в вышеприведённом коде – называются глобальными.

    Глобальные переменные видимы для любой функции (если только их не перекрывают одноимённые локальные переменные).

    Желательно сводить использование глобальных переменных к минимуму. В современном коде обычно мало или совсем нет глобальных переменных. Хотя они иногда полезны для хранения важнейших «общепроектовых» данных.


     Параметры

    Мы можем передать внутрь функции любую информацию, используя параметры (также называемые аргументами функции).

    В нижеприведённом примере функции передаются два параметра: from и text.


    function showMessage(from, text) { // аргументы: from, text

      alert(from + ': ' + text);

    }

     

    showMessage('Аня', 'Привет!'); // Аня: Привет! (*)

    showMessage('Аня', "Как дела?"); // Аня: Как дела? (**)


    Когда функция вызывается в строках (*) и (**), переданные значения копируются в локальные переменные from и text. Затем они используются в теле функции.

    Вот ещё один пример: у нас есть переменная from, и мы передаём её функции. Обратите внимание: функция изменяет значение from, но это изменение не видно снаружи. Функция всегда получает только копию значения:


    function showMessage(from, text) {

     

      from = '*' + from + '*'; // немного украсим "from"

     

      alert( from + ': ' + text );

    }

     

    let from = "Аня";

     

    showMessage(from, "Привет"); // *Аня*: Привет

     

    // значение "from" осталось прежним, функция изменила значение локальной переменной

    alert( from ); // Аня


     Параметры по умолчанию

    Если параметр не указан, то его значением становится undefined.

    Например, вышеупомянутая функция showMessage(from, text) может быть вызвана с одним аргументом:


    showMessage("Аня");


    Это не приведёт к ошибке. Такой вызов выведет "Аня: undefined". В вызове не указан параметр text, поэтому предполагается, что text === undefined.

    Если мы хотим задать параметру text значение по умолчанию, мы должны указать его после =:


    function showMessage(from, text = "текст не добавлен") {

      alert( from + ": " + text );

    }

     

    showMessage("Аня"); // Аня: текст не добавлен


    Теперь, если параметр text не указан, его значением будет "текст не добавлен"

    В данном случае "текст не добавлен" это строка, но на её месте могло бы быть и более сложное выражение, которое бы вычислялось и присваивалось при отсутствии параметра. Например:


    function showMessage(from, text = anotherFunction()) {

      // anotherFunction() выполнится только если не передан text

      // результатом будет значение text

    }


    Вычисление параметров по умолчанию

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

    В примере выше anotherFunction() будет вызываться каждый раз, когда showMessage() вызывается без параметра text.


    Использование параметров по умолчанию в ранних версиях JavaScript

    Ранние версии JavaScript не поддерживали параметры по умолчанию. Поэтому существуют альтернативные способы, которые могут встречаться в старых скриптах.

    Например, явная проверка на undefined:


    function showMessage(from, text) {

      if (text === undefined) {

        text = 'текст не добавлен';

      }

     

      alert( from + ": " + text );

    }


    …Или с помощью оператора ||:


    function showMessage(from, text) {

      // Если значение text ложно, тогда присвоить параметру text значение по умолчанию

      text = text || 'текст не добавлен';

      ...

    }


     Возврат значения

    Функция может вернуть результат, который будет передан в вызвавший её код.

    Простейшим примером может служить функция сложения двух чисел:


    function sum(a, b) {

      return a + b;

    }

     

    let result = sum(1, 2 );

    alert( result ); // 3


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

    Вызовов return может быть несколько, например:


    function checkAge(age) {

      if (age > 18) {

        return true;

      } else {

        return confirm('А родители разрешили?');

      }

    }

     

    let age = prompt('Сколько вам лет?', 18);

     

    if ( checkAge(age) ) {

      alert( 'Доступ получен' );

    } else {

      alert( 'Доступ закрыт' );

    }


    Возможно использовать return и без значения. Это приведёт к немедленному выходу из функции.


    Например:

    function showMovie(age) {

      if ( !checkAge(age ) ) {

        return;

      }

     

      alert( "Вам показывается кино" ); // (*)

      // ...

    }


    В коде выше, если checkAge(age) вернёт false, showMovie не выполнит alert.

    Результат функции с пустым return или без него – undefined

    Если функция не возвращает значения, это всё равно, как если бы она возвращала undefined:


    function doNothing() { /* пусто */ }

     

    alert( doNothing() === undefined ); // true

    Пустой return аналогичен return undefined:

    function doNothing() {

      return;

    }

     

    alert( doNothing() === undefined ); // true


    Никогда не добавляйте перевод строки между return и его значением

    Для длинного выражения в return может быть заманчиво разместить его на нескольких отдельных строках, например так:


    return

     (some + long + expression + or + whatever * f(a ) + f(b))


    Код не выполнится, потому что интерпретатор JavaScript подставит точку с запятой после return. Для него это будет выглядеть так:


    return;

     (some + long + expression + or + whatever * f(a ) + f(b))


    Таким образом, это фактически стало пустым return.

    Если мы хотим, чтобы возвращаемое выражение занимало несколько строк, нужно начать его на той же строке, что и return. Или, хотя бы, поставить там открывающую скобку, вот так:


    return (

      some + long + expression

      + or +

      whatever * f(a) + f (b)

      )


    И тогда всё сработает, как задумано.


     Выбор имени функции

    Функция – это действие. Поэтому имя функции обычно является глаголом. Оно должно быть простым, точным и описывать действие функции, чтобы программист, который будет читать код, получил верное представление о том, что делает функция.

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

    Например, функции, начинающиеся с "show" обычно что-то показывают.

    Функции, начинающиеся с…

    • "get…" – возвращают значение,
    • "calc…" – что-то вычисляют,
    • "create…" – что-то создают,
    • "check…" – что-то проверяют и возвращают логическое значение, и т.д.

    Примеры таких имён:

    showMessage(..)     // показывает сообщение

    getAge(..)          // возвращает возраст (в каком либо значении)

    calcSum(..)         // вычисляет сумму и возвращает результат

    createForm(..)      // создаёт форму (и обычно возвращает её)

    checkPermission(..) // проверяет доступ, возвращая true/false

    Благодаря префиксам, при первом взгляде на имя функции становится понятным что делает её код, и какое значение она может возвращать.

    Одна функция – одно действие

    Функция должна делать только то, что явно подразумевается её названием. И это должно быть одним действием.

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

    Несколько примеров, которые нарушают это правило:

    • getAge – будет плохим выбором, если функция будет выводить alert с возрастом (должна только возвращать его).
    • createForm – будет плохим выбором, если функция будет изменять документ, добавляя форму в него (должна только создавать форму и возвращать её).
    • checkPermission – будет плохим выбором, если функция будет отображать сообщение с текстом доступ разрешён/запрещён (должна только выполнять проверку и возвращать её результат).

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


    Сверхкороткие имена функций

    Имена функций, которые используются очень часто, иногда делают сверхкороткими.

    Например, во фреймворке jQuery есть функция с именем $. В библиотеке Lodash основная функция представлена именем _.

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


     Функции == Комментарии

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

    Небольшие функции не только облегчают тестирование и отладку – само существование таких функций выполняет роль хороших комментариев!

    Например, сравним ниже две функции showPrimesНет. Каждая из них выводит  простое число до n.

    Первый вариант использует метку nextPrime:


    function showPrimes(n) {

      nextPrime: for (let i = 2; i < n; i++ ) {

     

        for (let j = 2 ; j < i; j++) {

          if (i % j == 0) continue nextPrime;

        }

     

        alert( i ); // простое

      }

    }


    Второй вариант использует дополнительную функцию isPrimeНет для проверки на простое:


    function showPrimes(n) {

     

      for (let i = 2 ; i < n; i++) {

        if (!isPrime(i)) continue;

     

        alert(i);  // простое

      }

    }

     

    function isPrime(n) {

      for (let i = 2 ; i < n; i++) {

        if ( n % i == 0) return false;

      }

      return true;

    }


    Второй вариант легче для понимания, не правда ли? Вместо куска кода мы видим название действия (isPrime). Иногда разработчики называют такой код самодокументируемым.

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


     Итого

    Объявление функции имеет вид:


    function имя(параметры, через, запятую) {

      /* тело, код функции */

    }


    • Передаваемые значения копируются в параметры функции и становятся локальными переменными.
    • Функции имеют доступ к внешним переменным. Но это работает только изнутри наружу. Код вне функции не имеет доступа к её локальным переменным.
    • Функция может возвращать значение. Если этого не происходит, тогда результат равен undefined.

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

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

    Именование функций:

    • Имя функции должно понятно и чётко отражать, что она делает. Увидев её вызов в коде, вы должны тут же понимать, что она делает, и что возвращает.
    • Функция – это действие, поэтому её имя обычно является глаголом.
    • Есть много общепринятых префиксов, таких как: create…, show…, get…, check… и т.д. Пользуйтесь ими как подсказками, поясняющими, что делает функция.

    Функции являются основными строительными блоками скриптов. Мы рассмотрели лишь основы функций в JavaScript, но уже сейчас можем создавать и использовать их. Это только начало пути. Мы будем неоднократно возвращаться к функциям и изучать их всё более и более глубоко.



  • 2.7 POST и GET запросыэ



     Что такое HTTP?

    Протокол HTTP предназначен для обеспечения связи между клиентами и серверами.

    HTTP работает как протокол запроса-ответа между клиентом и сервером.

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

    Пример: клиент (обозреватель) отправляет HTTP-запрос на сервер; Затем сервер возвращает ответ клиенту. Ответ содержит сведения о состоянии запроса, а также может содержать запрошенное содержимое.


    Два метода HTTP-запроса: Get и POST

    Два часто используемых метода запроса-ответа между клиентом и сервером: Get и POST.

    • GET - Запрашивает данные из указанного ресурса
    • POST - Отправка данных для обработки в указанный ресурс


     Метод Get

    Обратите внимание, что строка запроса (пары «имя-значение») отправляется в URL-адрес запроса GET:

    /test/demo_form.php?name1=value1&name2=value2

    Некоторые другие заметки о запросах GET:

    • GET запросы могут кэшироваться
    • GET запросы остаются в истории браузера
    • GET запросы могут быть закладками
    • GET запросы никогда не должны использоваться при работе с конфиденциальными данными
    • GET запросы имеют ограничения по длине
    • GET запросы должны использоваться только для извлечения данных


     Метод POST

    Обратите внимание, что строка запроса (пары «имя-значение») отправляется в теле HTTP-сообщения запроса POST:

    POST /test/demo_form.php HTTP/1.1
    Host: html5css.ru
    name1=value1&name2=value2

    Некоторые другие примечания по запросам POST:

    • POST запросы никогда не кэшируются
    • Запросы POST не сохраняются в журнале обозревателя
    • Запросы POST не могут быть закладками
    • Запросы POST не имеют ограничений по длине данных


    GET

    POST

     

    Кнопка возврата/перезагрузка

    Безвредны

    Данные будут повторно отправлены (браузер должен предупредить пользователя о том, что данные будут повторно отправлены)

    Закладка

    Можно закладка

    Не может быть Закладка

    Кэшированные

    Может кэшироваться

    Не кэшируется

    Тип кодировки

    application/x-www-form-urlencoded

    application/x-www-form-urlencoded or multipart/form-data. Использование многокомпонентной кодировки для двоичных данных

    Истории

    Параметры остаются в журнале обозревателя

    Параметры не сохраняются в журнале обозревателя

    Ограничения по длине данных

    Да, при отправке данных метод Get добавляет данные в URL-адрес; и длина URL ограничена (максимальная длина URL составляет 2048 символов)

    Без ограничений

    Ограничения типа данных

    Разрешены только символы ASCII

    Никаких ограничений. Двоичные данные также разрешены

    Безопасности

    Get менее безопасен по сравнению с POST, поскольку отправляемые данные являются частью URL-адреса

    POST немного безопаснее, чем Get, поскольку параметры не сохраняются в журнале обозревателя или в журналах веб-сервера

    Видимость

    Данные видны всем в URL

    Данные не отображаются в URL-адресе


  • 2.8 Знакомство PhpMyAdmin



     phpMyAdmin

    Данная утилита позволяет нам работать с сервером баз данных MySQL. А если быть точнее, то phpMyAdmin позволяет:

    1. Создавать базу данных
    2. Создавать таблицы в базе данных
    3. Добавлять, удалять и редактировать данные в табицах
    4. Осуществлять поиск данных
    5. Устанавливать привилегии на базу данных, таблицу
    6. Делать бекап и восстанавливать базу данных
    7. И многое другое

    Т.е. phpMyAdmin позволяет делать первоначальные настройки базы данных и ее содержимого. А теперь обо всем этом подробно.


     Установка phpMyAdmin

    phpMyAdmin представляет собой набор html, css, javascript и php файлов — это небольшой сайт, который управляет MySQL. Установка phpMyAdmin представляет собой обычное копирование файлов на Ваш web-сервер. После того, как мы установили phpMyAdmin в адресной строке браузера набираем адрес <Ваш сайт>/phpMyAdmin и попадаем в окно авторизации phpMyAdmin



    В поле “Пользователь” вводим root, а в поле “Пароль” вводи пароль, который Вы установили для root пользователя при установке MySQL.


     Интерфейс phpMyAdmin

    После прохождения авторизации мы попадаем в главное окно


    В левой части мы видим ссылки для быстрого перехода:


    Ниже них расположены названия баз данных, которые находятся на сервер MySQL. Тут будьте внимательны базы: information_shema, mysql, perfomance_shema — это = служебные базы данных и если Вы не знаете, за что они отвечают, то лучше их не трогать. В правой части или основной вверху мы видим меню


    ниже этого меню мы видим:

    1. Окно основных настроек


    2. Окно настроек внешнего вида


    3. Информационное окно о сервере баз данных


    4. Информационное окно о WEB-сервере


    5. Информационное окно о phpMyAdmin


     Создание базы данных при помощи phpMyAdmin

    Для того чтобы приступить к созданию базы данных перейдем в меню “Базы данных”



    В поле вводим название базы данных и жмем “Создать”




     

     Удаление базы данных

    Для того, чтобы удалить базу данных необходимо в окне баз данных выбрать необходимую базу данных и нажать “Удалить"



    И тут мы увидим еще одну замечательную особенность phpMyAdmin, которая понравиться для тех, кто только изучает SQL-язык: phpMyAdmin показывает нам запрос.
    Для удаления базы данных необходимо подтвердить запрос.




     Работа с базой данных через phpMyAdmin

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



    Давайте создадим таблицу test в нашей базе данных. Для этого в окне нашей базы данных в поле введем название таблицы, а в поле количество столбцов поставим, например, 2 и нажмем “Вперед”



    В следующем окне нам предложат заполнить данные о столбцах:
    1. Имя — имя столбца
    2. Тип — тип столбца
    3. Длина — длина столбца
    4. По умолчанию — значение, которое будет подставлено по умолчаню, если Вы это указали
    5. Сравнение — как будет осуществляться поиск данных
    6. Атрибуты — атрибуты столбца
    7. Null — может ли столбец быть пустым
    8. Индекс — индекс поля
    9. A_I — является ли данный столбец с автоматическим приращением
    10. Комментарий — комментарий к данному столбцу
    Также мы должны указать тип столбцов.
    После ввода всех необходимых данных жмем “Сохранить”



    Мы видим, что появилась наша таблица


    Теперь мы можем:
    1. выполнить SQL-запрос — это делается в меню “SQL”
    2. осуществить поиск данных в нашей базе — это делается в меню “Поиск”
    3. можем осуществить запрос по шаблону, который можно сделать в меню “Запрос по шаблону”
    4. Экспортировать данные базы в различные форматы — это делается в меню “Экспорт”
    5. Импортировать данные в базу в меню “Импорт”
    6. Установить привилегии на базу данных: создать пользователей для данной базы и настроить их доступ к данным — это выполняется в меню “Привилегии”
    7. Можем удалить таблицу. Для выбрать необходимую таблицу и нажать “Удалить”


     Работа с данными

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



    После чего мы увидим структуру данной таблицы


    Для того, чтобы добавить данные в таблицу необходимо перейти в меню “Вставить” и приступить к добавлению данных. А вообще данные в таблице мы можем:
    1. Просматривать.
    2. Добавлять.
    3. Удалять.
    4. Изменять.
    5. Копировать.
    6. Осуществлять поиск по различным критериям.


     Добавление пользователя

    В phpMyAdmin мы мжем добавлять пользователей, назначая им определенные привилегии. Пользователя мы можем создать как для сервера баз данных целиком, так и для отдельной базы данных. Давайте на примере нашей тестовой базы данных test создадим пользователя и назначим ему определенные привилегии. Для этого перейдем в нашу базу данных test и в меню жмем привилегии.



    В следующем окне жмем “Добавить пользователя”


    В следующем окне заполняем все поля:
    1. Имя пользователя — логин
    2. Хост — выбираем ограничение доступа: с любой машины, с локальной машины, использовать таблицу хостов или использовать текстовое поле.
    3. Пароль — вводим пароль для данной учетной записи (если Вы генерируете пароль, то ничего вводить не надо)
    4. Подтверждение — повторяем пароль
    5. Создать пароль — при нажатии на кнопку “Генерировать” phpMyAdmin автоматически сгенерирует пароль
    После заполнения всех полей жмем “Добавить пользователя”



    Если пользователь успешно добавлен, то Вы увидите следующее окно



    Для изменения привилегий жмем “Редактирование привилегий” напротив необходимого пользователя.


  • 2.9 Основы SQL




     СУБД

    Система управления базами данных (СУБД) — это отдельная программа, которая работает как сервер, независимо от PHP.
    Создавать свои базы данных, таблицы и наполнять их данными можно прямо из этой же программы, но для выполнения этих операций прежде придётся познакомиться с ещё одним языком программирования — SQL.


     SQL

    SQL или Structured Query Language (язык структурированных запросов) — язык программирования, предназначенный для управления данными в СУБД. Все современные СУБД поддерживают SQL.

    На языке SQL выражаются все действия, которые можно провести с данными: от записи и чтения данных, до администрирования самого сервера СУБД.
    Для повседневной работы совсем не обязательно знать весь этот язык; достаточно ознакомиться лишь с основными понятиями синтаксиса и ключевыми словами. Кроме того, SQL очень простой язык по своей структуре, поэтому его освоение не составит большого труда.

    Язык SQL — это в первую очередь язык запросов, а кроме того, он очень похож на естественный язык.
    Каждый раз, когда требуется прочитать или записать любую информацию в БД, требуется составить корректный запрос. Такой запрос должен быть выражен в терминах SQL.

    Например, чтобы вывести на экран все записи из таблицы города, составим такой запрос:


    ПРОЧИТАТЬ всё ИЗ ТАБЛИЦЫ 'города'


    Если перевести этот запрос на язык SQL, то корректным результатом будет:


    SELECT * FROM `cities`


    Теперь напишем запрос на добавление в таблицу города нового города:


    ВСТАВЬ В ТАБЛИЦУ `города` (`имя города`) СО ЗНАЧЕНИЕМ ('Санкт-Петербург')


    Перевод на SQL:


    INSERT INTO `cities` (`name`) VALUES (Санкт-Петербург’)


    Эта команда создаст в таблице ‘города’ новую запись, где полю ‘имя города’ будет присвоено значение ‘Санкт-Петербург’.

    С помощью SQL можно не только добавлять и читать данные, но и:

    • удалять и обновлять записи в таблицах;
    • создавать и редактировать сами таблицы;
    • производить операции над данными: считать сумму, получать самое большое или малое значение, и так далее;
    • настраивать работу сервера СУБД.



  • 2.10 Основы объектного ориентированного программирования



     ООП

    Объектно-ориентированное программирование (ООП) – это методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования.

    Класс – это шаблон, описание ещё не созданного объекта. Класс содержит данные, которые описывают строение объекта и его возможности, методы работы с ним.

    Объект — экземпляр класса. То, что «рождено» по «чертежу», то есть по описанию из класса.

    В качестве примера объекта и класса можно привести технический чертёж для изготовления детали — это класс. Выточенная же на станке по размерам и указаниям из чертежа деталь – объект.

    Появление объектно-ориентированного программирования стало результатом возросших требований к функционалу программ, когда описывать объект приходилось раз за разом в разных участках кода. Тогда и было введено понятие класса, параметры которого задавались единожды, а после в коде оставлялись только ссылки на класс, чтобы код самостоятельно «собрал» объект.


     Понятие абстракции в ООП

    Абстракция — это придание объекту характеристик, которые отличают его от всех других объектов, четко определяя его концептуальные границы. Основная идея состоит в том, чтобы отделить способ использования составных объектов данных от деталей их реализации в виде более простых объектов.

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

    Три основных принципа ООП

    Объектно-ориентированное программирование базируется на трёх основных принципах – инкапсуляция, полиморфизм, наследование. Рассмотрим их подробнее:

     

     Инкапсуляция

    Инкапсуляция — свойство языка программирования, позволяющее пользователю не задумываться о сложности реализации используемого программного компонента (что у него внутри?), а взаимодействовать с ним посредством предоставляемого интерфейса (публичных методов и членов), а также объединить и защитить жизненно важные для компонента данные. При этом пользователю предоставляется только спецификация (интерфейс) объекта.


    Пользователь может взаимодействовать с объектом только через этот интерфейс. Реализуется с помощью ключевого слова: public. Пользователь не может использовать закрытые данные и методы. Реализуется с помощью ключевых слов: private, protected, internal.

    Пример использования инкапсуляции в языке С++:

     

    class A

    {

     public:

       int a, b; //данные открытого интерфейса

       int ReturnSomething(); //метод открытого интерфейса

     private:

       int Aa, Ab; //скрытые данные

       void Do_Something(); //скрытый метод

    };

    Класс А инкапсулирует свойства Aa, Ab и метод Do_Something(), представляя внешний интерфейс ReturnSomething, a, b.

     

    Инкапсуляцию применяют:

    • когда нужно сохранить некоторый участок кода без изменений со стороны пользователя;
    • когда нужно ограничить доступ к коду – в связи с уникальностью используемых техник, которые автор хочет оставить «при себе»;
    • когда изменение кода повлечёт за собой неработоспособность программы или её взлом.


     Наследование

    Наследование — способность в объектно-ориентированном программировании построить новый класс на основе уже заданного. При этом функционал может как полностью совпадать, так и отличаться. Класс-донор называется в таком случае родительским или базовым, а его «потомок» — наследником, дочерним классом. Наследование требует определения ещё одного понятия:

     

    Прототип — объект-образец, на основе которого «рождаются» другие объекты, полностью копируя его или изменяясь в процессе. При изменении в прототипе в копиях также происходят соответствующие изменения.

     

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

     

     Полиморфизм

    Полиморфизм — способность объектов самим определять, какие методы они должны применить в зависимости от того, где именно в коде они находятся. То есть, объект может изменяться в зависимости от своего местоположения и действовать по-разному, что позволяет не заводить лишних структур. Иначе говоря: один интерфейс — множество решений.

     

    Полиморфизм позволяет понизить процент повторного использования кода и сократить тем самым размер программы и временные затраты на её написание.




  • 2.11 Ведение Model View Controller



     MVC

    Model-View-Controller (MVC) — это архитектурный шаблон, который разделяет приложение на три основных логических компонента: модель , представление и контроллер. Каждый из этих компонентов создан для обработки определенных аспектов разработки приложения. MVC является одной из наиболее часто используемых отраслевых сред разработки веб-приложений для создания масштабируемых и расширяемых проектов.


     Компоненты MVC

    Ниже приведены компоненты MVC —


     Модель

    Компонент Model соответствует всей логике, связанной с данными, с которой работает пользователь. Это может представлять либо данные, которые передаются между компонентами View и Controller, либо любые другие данные, связанные с бизнес-логикой. Например, объект Customer будет извлекать информацию о клиенте из базы данных, манипулировать ею и обновлять данные обратно в базу данных или использовать ее для визуализации данных.


     Представление

    Компонент View используется для всей логики пользовательского интерфейса приложения. Например, представление Customer будет включать все компоненты пользовательского интерфейса, такие как текстовые поля, раскрывающиеся списки и т. Д., С которыми взаимодействует конечный пользователь.


     Контроллер

    Контроллеры действуют как интерфейс между компонентами Model и View для обработки всей бизнес-логики и входящих запросов, манипулирования данными с использованием компонента Model и взаимодействия с представлениями для получения окончательного результата. Например, контроллер клиента будет обрабатывать все взаимодействия и входные данные из представления клиента и обновлять базу данных, используя модель клиента. Тот же контроллер будет использоваться для просмотра данных клиента.

    • 2.12 Разработка API



       API

      Аббревиатура API расшифровывается как «Application Programming Interface» (интерфейс программирования приложений, программный интерфейс приложения). Большинство крупных компаний на определённом этапе разрабатывают API для клиентов или для внутреннего использования. Чтобы понять, как и каким образом API применяется в разработке и бизнесе, сначала нужно разобраться, как устроена «всемирная паутина».


       Всемирная паутина и удалённые серверы

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

      При введении в адресную строку браузера www.facebook.com на удалённый сервер Facebook отправляется соответствующий запрос. Как только браузер получает ответ, то интерпретирует код и отображает страницу.

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

      Большинство современных веб-приложений предоставляют API, которые клиенты могут использовать для взаимодействия с приложением. Качественно спроектированный API должен поддерживать следующее:

      • Независимость от платформы. Любой клиент должен иметь возможность вызывать API, независимо от того, как API реализован внутренне. Для этого требуется использование стандартных протоколов, а также наличие механизма, при котором клиент и веб-службы могут согласовать формат данных для обмена.
      • Развитие службы. Веб-API должен иметь возможность развиваться и расширять набор функций независимо от клиентских приложений. По мере развития API имеющиеся клиентские приложения должны продолжать работать без изменений. Все функции должны быть доступными, чтобы клиентские приложения могли полноценно их использовать.

      API работает на 3 уровнях:

      Приложение: Это приложения, которые вы используете на смартфоне, или ПО.
      Программирование: Программисты используют API, чтобы писать код.
      Интерфейс: Как вы взаимодействуете с приложением.

      Пример: Представьте официанта в ресторане. Вы — клиент, выбираете заказ в меню. Кухня — исполнитель вашего заказа.

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

      Официант принимает ваш заказ, приносит его на кухню, говорит, что вы заказали. Затем доставляет ответ, или еду вам. Более того, если все сделано правильно, ваш заказ не упадет.


       Виды API

      Публичные API выпускаются такими компаниями, как Slack и Shopify, в надежде на то, что разработчики будут их использовать на своих платформах. Компании делятся набором вводных параметров, которые разработчики используют, чтобы достичь какого-то результата.

      Публичное API можно использовать без проблем — доступ к документации можно получить без проблем.

      Приватные API используются внутри компании. Если у компании много программных продуктов, приватное API используется, чтобы программы разговаривали между собой. Компоненты API могут меняться по желанию компании, тогда как изменения в публичном API может вызвать отчаянные протесты.



    • 2.13 Медиа-запросы

      • CSS-директивы - Специальные инструкции, которые начинаются с @


      @media условия { свойства } это правила CSS, которые позволяют управлять стилями элементов в зависимости от значений технических параметров устройств (предназначено для создания адаптивных дизайнов)



      Медиа-характеристики
      width - позволяет задать условие на равенство ширины области просмотра определённому значению. Для определения диапазона можно использовать min-width и max-width
      @media (width: 546px) { .класс { font size: 15px; } }
      height - для задания условий в отношении высоты viewpor0 (можно использовать min-height и max-height @media (height: 546px) { .класс { font size: 15px; } }
      orientation можно установить те или иные стили в зависимости от того, в каком режиме (альбомном landscape или портретном portrait) отображается сайт/ @media (orientation: landscape) { .класс { font size: 15px; } }
      @media (orientation: portrait) { .класс { font size: 15px; } }
      aspect-ration, min-aspect-ratio и max-aspect-ratio позволяют задавать стили в зависимости от соотношения сторон viewport. @media (aspect ration: 9/16) { .класс { font size: 15px; } }
      @media (aspect ration: 1/1) { .класс { font size: 15px; } }
      resolution, min-resolution и max-resolution можно использовать, когда нужно задать стили в зависимости от плотности пикселей устройства. @media (resolution: 50dpi) { .класс { font size: 15px; } }


      Типы устройств
      all – для всех @media all { .класс { font size: 15px; } }
      print - для принтеров и в режиме предварительного просмотра страницы перед печатью @media print { .класс { font size: 15px; } }
      screen – для устройств с экранами @media screen { .класс { font size: 15px; } }
      speech – для программ чтения с экрана @media speech { .класс { font size: 15px; } }

      Логические операторы and, , (запятая), not и only предназначены для создания сложных медиа-запросов
      • Оператор and используется для объединения нескольких условий. В этом случае их результат будет истинным, когда каждое из них будет истинным. Пример: @media (min width: 600px) and (max width: 800px) { .класс { fon0 size: 15px; }
      • Применение стилей, когда необходимо лишь выполнение одного из указанных условий, достигается посредством разделения их между собой с помощью , (запятой). Пример: @media screen, (orientation: landscape) { .класс { fon0 size: 15px; }
      • Ключевое слово not используется для отрицания. При использовании not с and отрицание работает для всего медиа-запроса.
        При этом, когда указываем not необходимо обязательно задавать тип устройства.
        Пример: @media not screen, not (min width: 411px) { .класс { fon0 size: 15px; } } 
        @media not screen and (min wid0h: 411px) and (min heigh0: 731px) { .класс { fon0 size: 15px; } }

        *Ещё есть оператор only, он предназначен для того, чтобы браузеры, которые не поддерживают CSS3 медиа-запросы их игнорировали. В настоящее время это уже не актуально, поэтому использовать only не нужно. 

      • 2.14 сетка Flexbox

        Флекс и блочная модель (принципы)

        • Размеры флекс-элементов рассчитываются как в обычной блочной модели: рамки + отступы + размеры содержания
        • Работает box-sizing
        • Флекс-элементы по умолчания ужимаются под содержимое
        • Не работает float
        • Внешние отступы не схлопываются и не выпадают

        Определение базовых размеров
        • flex-basis: auto — значение по умолчанию.
        • Если flex-basis задано, то оно переопределяет width или height (в зависимости от направления главной оси)
        • Внутренние отступы и рамки тоже участвуют в расчeте базовых размеров
        fdgdf

        Изменение размеров гибких элементов
        • Перераспределение происходит после этапа определения базовых размеров
        • Флекс-элементы умеют перераспределять свободное пространство и за счeт него изменять свои размеры (уменьшать или увеличивать)
        flex-grow
        • flex-grow: 0 — значение по умолчанию
        • Если flex-grow больше 0, то элемент может поглотить свободное пространство и увеличиться
        • Если элементов с положительным flex-grow несколько, они делят свободное пространство пропорционально своим flex-grow


        прапр выаыва

        Использование flex-grow
        • Не используйте flex-grow для задания точных ширин
        • Используйте flex-grow для «резиновых» раскладок и «адаптивности без медиавыражений»

        flex-shrink
        • Если есть отрицательное пространство, то элемент может его поглотить и уменьшиться. 
        • Для этого flex-shrink должен быть больше 0.
        • flex-shrink: 1 — значение по умолчанию.
        • Если элементов с положительным flex-shrink несколько, то они делят отрицательное пространство пропорционально своим flex-shrink и базовым размерам.

        margin:auto (автоматические отступы)
        • Работает во всех направлениях.
        • «Съедает» свободное место.
        • Если у нескольких элементов есть автоматические отступы, то свободное место делится поровну.
        • Свободное место «съедается» до работы выравниваний — выравнивания «ломаются».
        вапва

        Выравнивание элементов
        • Выравнивание вдоль главной оси.
        • Выравнивание вдоль поперечной оси.
        • Выравнивание работает, если осталось свободное пространство, и если оно не съедено жадными элементами и автоматическими отступами.

        Выравнивание элементов вдоль главной оси: justify-content

        • flex-end (к концу края)
        • center (разместить элементы по центру гл.оси)
        • space-between (первый элемент к началу, последний к концу гл.оси, остальные размещаются на одинаковое расстояние
        • space-around (элементы равномерно распределены вдоль гл.оси)
        ывава

        Выравнивание поперёк главной оси align-items:

        • stetch (растягиваются по высоте)
        • start (элементы в начале поперечной оси)
        • end (элементы в конце поперечной оси)
        • center (по центру поперечной оси)
        • baseline (элементы выровнены так, что их базовые линии совпадают)
        ываыва

        Эгоистичное выравнивание, align-self - выравнивает flex-элементы по текущей flex-линии, переопределяя значение свойства align-items
        sdfdsf

        Ограничение размеров
        • Минимальные и максимальные размеры (min-width, max-width, min-height и max-height) не влияют на базовый разме
        • Они применяются к элементам в самом конце работы механизма расчёта размеров и свободного пространства
        • Возможны эффекты «выпадания» из потока
        Построение сеток на флексбоксах
        • Всегда явно задавайте размер колонок: width или flex-basis
        • Расстояния между колонок можно задавать: с помощью justify-content, если отступы одинаковые или с помощью margin, если отступы разные
        • Если количество колонок может изменяться (карточный интерфейс), то margin предпочтительнее
        • Следите за псевдоэлементами у флекс-контейнера
        • flex-grow не подходит, если нужно добиться точного соответствия макету

        • Резина (резиновая вёрстка) вёрстка с использованием процентов.
        • Фикс (фиксированная вёрстка) вёрстка с использованием пикселей.
        • 2.15 Сетка Grid

          Дисплей Grid это новая модель шаблонов, оптимизированная для создания двумерных макетов. Она подходит для: списков товаров / карточек, форм, галерей и всего, что требует точного и отзывчивого позиционирования.

          display: grid  Превращает элемент в grid контейнер
          grid-template-rows: ряд  Выстраивает ряды в гриде. Каждое значение представляет размер ряда. (пример ряда: 50px 50px 50px
          grid-template-columns: колонка  Тоже самое, что и grid-template-rows, только определяет размер колонки в гридах
          grid-gap: значение Выставляет расстояние между грид элементами

          Функция repeat() - используется для повторяющихся объявлений значения размера элемента.
          Пример: grid-template-rows: repeat(5, 50px);

          • 2.16 SASS/ SCSS

            Что такое CSS-препроцессоры?

            Это надстройка над CSS, которая добавляет ранее недоступные возможности для CSS, с помощью новых синтаксических конструкций.

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

            Препроцессоры нацелены на: 

            • Читабельность
            • Структурированность и логичность
            • Производительность

            Что такое SASS?

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

            *Браузеры не воспринимают файлы, написанные на SASS, они не могут прочитать код внутри них и не могут понять что необходимо сделать. Из-за этого, весь SASS необходимо конвертировать в привычные CSS файлы.

            В чём отличия между SASS и SCSS?

            Многие слышали про SASS и SCSS и думают что это разные технологии. На самом деле, обе технологии являются один и тем же и отличаются лишь синтаксисом написания. В SASS все вложенные свойства выделяются отступами, при чем очень важно соблюдать отступы и их количество. SCSS более приближен к обычному CSS и все вложенные стили записываются через фигурные скобки - {}.

            • 2.17 Bootstrap

              Bootstrap - это фреймворк CSS, включающий в себя HTML и Javascript. В библиотеке представлены шаблоны, помогающие создавать визуальные эффекты и подстраиваться под различные размеры экрана.

              Bootstrap верстка популярный способ быстро создать веб сайт. Адаптивная верстка Bootstrap часть данной работы. Все сайты, что строятся на Bootstrap имеют продуманную структуру и являются адаптивными по умолчанию.

              Почему используют Bootstrap?

              Bootstrap содержит множество готовых стилей и JavaScript скриптов для создания веб сайта. Написание стилей для сайта можно значительно сократить за счёт использования уже готовых решений от Bootstrap.

              Как работать с Bootstrap?

              Принцип работы с Bootstrap прост. Вам предстоит:

              • скачать или подключить Bootstrap при помощи CDN
              • выполнить верстку сайта с помощью Bootstrap, используя подготовленные стили

              Сетка в Bootstrap

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


              54 45645

               Контейнер

              .container масштабируется адаптивно по ширине экрана, так что в конце концов он может стать шириной на весь экран
              Колонки внутри .row не всегда располагаются горизонтально вдоль вьюпорта, поэтому Row это именно группа колонок .col, а не просто горизонтальная строка.
              Только .col можно размещать внутри .row, а контент размещается уже внутри .col
              Так же очень важно упомянуть, что .row имеет display: flex. А как потомок в Flexbox, “колонка” в каждой строке одной и той же высоты.

              Правила сетки:
              • Колонки должны быть прямыми потомками Row
              • Row используются только для того, чтобы включать в себя колонки и не для ничего больше.
              • Row должны быть помещены внутри контейнера
              Классическая сетка Bootstrap имеет 12 колонок (.col)  sadasd
              Таким образом, колонки могут быть равномерно разделены на 12 частей. Вот пример, 6 колонок (12/6=2)
              xzczxc

              Ширина колонки может изменяться в зависимости от ширины экрана, есть 5 адаптивных рядов (брейкпоинтов)
              Адаптивные брейкпоинты, основаны на ширине экрана
              • (xs) ширина экрана < 576px. Это стандарт.
              • sm ширина экрана ≥ 576px
              • md ширина экрана ≥ 768px
              • lg ширина экрана ≥ 992px
              • xl ширина экрана ≥ 1200px