суббота, 2 декабря 2017 г.

[Мой конспект 3]

filter()

sort()

setTimeout

clearTimeout

setInterval

clearInterval

Рекурсивный setTimeout

Рекурсия

Сanvas

Всплытие 

Что же такое хоистинг переменных ?

Интерпретатор JavaScript всегда незаметно для нас перемещает («поднимает») объявления функций и переменных в начало области видимости.То есть переменные могут быть доступны до их объявления.

Garbage collector

пятница, 1 декабря 2017 г.

[Мой конспект 1]

Async / Defer

Браузер загружает и отображает HTML постепенно. Особенно это заметно при медленном интернет-соединении: браузер не ждёт, пока страница загрузится целиком, а показывает ту часть, которую успел загрузить.
Если браузер видит тег <script>, то он по стандарту обязан сначала выполнить его, а потом показать оставшуюся часть страницы.
Такое поведение называют «синхронным». Как правило, оно вполне нормально, но есть важное следствие.
Если скрипт – внешний, то пока браузер не выполнит его, он не покажет часть страницы под ним.

И здесь вопрос – действительно ли мы этого хотим? То есть, действительно ли оставшуюся часть страницы нельзя показывать до загрузки скрипта?


Атрибут async


Поддерживается всеми браузерами, кроме IE9-. Скрипт выполняется полностью асинхронно. То есть, при обнаружении <script async src="..."> браузер не останавливает обработку страницы, а спокойно работает дальше. Когда скрипт будет загружен – он выполнится.
Атрибут defer
Поддерживается всеми браузерами, включая самые старые IE. Скрипт также выполняется асинхронно, не заставляет ждать страницу, но есть два отличия от async.
Первое – браузер гарантирует, что относительный порядок скриптов с defer будет сохранён.
То есть, в таком коде (с async) первым сработает тот скрипт, который раньше загрузится:
<script src="1.js" async></script>
<script src="2.js" async></script>
А в таком коде (с defer) первым сработает всегда 1.js, а скрипт 2.js, даже если загрузился раньше, будет его ждать.
<script src="1.js" defer></script>
<script src="2.js" defer></script>
Поэтому атрибут defer используют в тех случаях, когда второй скрипт 2.js зависит от первого 1.js, к примеру – использует что-то, описанное первым скриптом.
Второе отличие – скрипт с defer сработает, когда весь HTML-документ будет обработан браузером.
Например, если документ достаточно большой…
<script src="async.js" async></script>
<script src="defer.js" defer></script>

Много много много букв
…То скрипт async.js выполнится, как только загрузится – возможно, до того, как весь документ готов. А defer.js подождёт готовности всего документа.
Это бывает удобно, когда мы в скрипте хотим работать с документом, и должны быть уверены, что он полностью получен.

Итого:

  • Скрипты вставляются на страницу как текст в теге <script>, либо как внешний файл через <script src="путь"></script>
  • Специальные атрибуты async и defer используются для того, чтобы пока грузится внешний скрипт – браузер показал остальную (следующую за ним) часть страницы. Без них этого не происходит.
  • Разница между async и defer: атрибут defer сохраняет относительную последовательность скриптов, а async – нет. Кроме того, defer всегда ждёт, пока весь HTML-документ будет готов, а async – нет.

Use Strict

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

Use strict также можно указывать в начале функций, тогда строгий режим будет действовать только внутри функции.


В старом стандарте JavaScript разрешалось создавать переменную и без var, просто присвоив ей значение:
num = 5; // переменная num будет создана, если ее не было
В режиме "use strict" так делать уже нельзя.

Var / Let / Const

У объявлений переменной через let есть три основных отличия от var:
  1. Область видимости переменной let – блок {...}.
    Как мы помним, переменная, объявленная через var, видна везде в функции.
    Переменная, объявленная через let, видна только в рамках блока {...}, в котором объявлена.
    Это, в частности, влияет на объявления внутри if, while или for.
    Например, переменная через var:
    var apples = 5;
    
    if (true) {
      var apples = 10;
    
      alert(apples); // 10 (внутри блока)
    }
    
    alert(apples); // 10 (снаружи блока то же самое)
    В примере выше apples – одна переменная на весь код, которая модифицируется в if.
    То же самое с let будет работать по-другому:
    
    
    
    
    
    
    
    
    
    let apples = 5; // (*)
    
    if (true) {
      let apples = 10;
    
      alert(apples); // 10 (внутри блока)
    }
    
    alert(apples); // 5 (снаружи блока значение не изменилось)
    Здесь, фактически, две независимые переменные apples, одна – глобальная, вторая – в блоке if.
    Заметим, что если объявление let apples в первой строке (*) удалить, то в последнем alert будет ошибка: переменная не определена.
    Это потому что переменная let всегда видна именно в том блоке, где объявлена, и не более.
  2. Переменная let видна только после объявления.
    Как мы помним, переменные var существуют и до объявления. Они равны undefined:
    alert(a); // undefined
    
    var a = 5;
    С переменными let всё проще. До объявления их вообще нет.
    Такой доступ приведёт к ошибке:
    
    alert(a); // ошибка, нет такой переменной
    
    let a = 5;
    Заметим также, что переменные let нельзя повторно объявлять. То есть, такой код выведет ошибку:
    let x;
    let x; // ошибка: переменная x уже объявлена
    Это – хоть и выглядит ограничением по сравнению с var, но на самом деле проблем не создаёт. Например, два таких цикла совсем не конфликтуют:
    // каждый цикл имеет свою переменную i
    for(let i = 0; i<10; i++) { /* … */ }
    for(let i = 0; i<10; i++) { /* … */ }
    
    alert( i ); // ошибка: глобальной i нет
    При объявлении внутри цикла переменная i будет видна только в блоке цикла. Она не видна снаружи, поэтому будет ошибка в последнем alert.
  3. При использовании в цикле, для каждой итерации создаётся своя переменная.
    Переменная var – одна на все итерации цикла и видна даже после цикла:
    for(var i=0; i<10; i++) { /* … */ }
    
    alert(i); // 10
    С переменной let – всё по-другому.
    Каждому повторению цикла соответствует своя независимая переменная let. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой будет та переменная, которая была при соответствующей итерации.
    Это позволяет легко решить классическую проблему с замыканиями, описанную в задаче Армия функций.
    
    
    
    
              function makeArmy() {
    
      let shooters = [];
    
      for (let i = 0; i < 10; i++) {
        shooters.push(function() {
          alert( i ); // выводит свой номер
        });
      }
    
      return shooters;
    }
    
    var army = makeArmy();
    
    army[0](); // 0
    army[5](); // 5
    Если бы объявление было var i, то была бы одна переменная i на всю функцию, и вызовы в последних строках выводили бы 10 (подробнее – см. задачу Армия функций).
    А выше объявление let i создаёт для каждого повторения блока в цикле свою переменную, которую функция и получает из замыкания в последних строках.

const

Объявление const задаёт константу, то есть переменную, которую нельзя менять:
const apple = 5;
apple = 10; // ошибка
В остальном объявление const полностью аналогично let.
Заметим, что если в константу присвоен объект, то от изменения защищена сама константа, но не свойства внутри неё:
const user = {
  name: "Вася"
};

user.name = "Петя"; // допустимо
user = 5; // нельзя, будет ошибка
То же самое верно, если константе присвоен массив или другое объектное значение.
константы и КОНСТАНТЫ
Константы, которые жёстко заданы всегда, во время всей программы, обычно пишутся в верхнем регистре. Например: const ORANGE = "#ffa500".
Большинство переменных – константы в другом смысле: они не меняются после присвоения. Но при разных запусках функции это значение может быть разным. Для таких переменных можно использовать const и обычные строчные буквы в имени.

Итого

Переменные let:
  • Видны только после объявления и только в текущем блоке.
  • Нельзя переобъявлять (в том же блоке).
  • При объявлении переменной в цикле for(let …) – она видна только в этом цикле. Причём каждой итерации соответствует своя переменная let.
Переменная const – это константа, в остальном – как let.

Alert / Confirm / Prompt

  • alert выводит сообщение.
  • prompt выводит сообщение и ждёт, пока пользователь введёт текст, а затем возвращает введённое значение или null, если ввод отменён (CANCEL/Esc).
  • confirm выводит сообщение и ждёт, пока пользователь нажмёт «OK» или «CANCEL» и возвращает true/false.

If / Else / Else if

Краткая форма 
условие ? значение1 : значение2

Switch

Конструкция switch заменяет собой сразу несколько if.
Она представляет собой более наглядный способ сравнить выражение сразу с несколькими вариантами.

Синтаксис

Выглядит она так:
switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}
  • Переменная x проверяется на строгое равенство первому значению value1, затем второму value2 и так далее.
  • Если соответствие установлено – switch начинает выполняться от соответствующей директивы case и далее, до ближайшего break (или до конца switch).
  • Если ни один case не совпал – выполняется (если есть) вариант default.
При этом case называют вариантами switch.
Если break нет, то выполнение пойдёт ниже по следующим case, при этом остальные проверки игнорируются.
Пример без break:











var a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Маловато' );
  case 4:
    alert( 'В точку!' );
  case 5:
    alert( 'Перебор' );
  default:
    alert( 'Я таких значений не знаю' );
}
В примере выше последовательно выполнятся три alert:
alert( 'В точку!' );
alert( 'Перебор' );
alert( 'Я таких значений не знаю' );
В case могут быть любые выражения, в том числе включающие в себя переменные и функции.
Например:







var a = 1;
var b = 0;

switch (a) {
  case b + 1:
    alert( 1 );
    break;

  default:
    alert('нет-нет, выполнится вариант выше')
}

Группировка case

Несколько значений case можно группировать.
В примере ниже case 3 и case 5 выполняют один и тот же код:












var a = 2+2;

switch (a) {
  case 4:
    alert('Верно!');
    break;

  case 3:                    // (*)
  case 5:                    // (**)
    alert('Неверно!');
    alert('Немного ошиблись, бывает.');
    break;

  default:
    alert('Странный результат, очень странный');
}
При case 3 выполнение идёт со строки (*), при case 5 – со строки (**).
Следующий пример принимает значение от посетителя.
var arg = prompt("Введите arg?")
switch (arg) {
  case '0':
  case '1':
    alert( 'Один или ноль' );

  case '2':
    alert( 'Два' );
    break;

  case 3:
    alert( 'Никогда не выполнится' );

  default:
    alert('Неизвестное значение: ' + arg)
}
Что оно выведет при вводе числа 0? Числа 1? 2? 3?
Подумайте, выпишите свои ответы, исходя из текущего понимания работы switch и потом читайте дальше…
  • При вводе 0 выполнится первый alert, далее выполнение продолжится вниз до первого break и выведет второй alert('Два'). Итого, два вывода alert.
  • При вводе 1 произойдёт то же самое.
  • При вводе 2, switch перейдет к case '2', и сработает единственный alert('Два').
  • При вводе 3, switch перейдет на default. Это потому, что prompt возвращает строку '3', а не число. Типы разные. Оператор switch предполагает строгое равенство ===, так что совпадения не будет.

For

Чаще всего применяется цикл for. Выглядит он так:
for (начало; условие; шаг) {
  // ... тело цикла ...
}
Пример цикла, который выполняет alert(i) для i от 0 до 2 включительно (до 3):
var i;

for (i = 0; i < 3; i++) {
  alert( i );
}
Здесь:
  • Начало: i=0.
  • Условие: i<3.
  • Шаг: i++.
  • Тело: alert(i), т.е. код внутри фигурных скобок (они не обязательны, если только одна операция)
Цикл выполняется так:
  1. Начало: i=0 выполняется один-единственный раз, при заходе в цикл.
  2. Условие: i<3 проверяется перед каждой итерацией и при входе в цикл, если оно нарушено, то происходит выход.
  3. Тело: alert(i).
  4. Шаг: i++ выполняется после тела на каждой итерации, но перед проверкой условия.
  5. Идти на шаг 2.
Иными словами, поток выполнения: начало → (если условие → тело → шаг) → (если условие → тело → шаг) → … и так далее, пока верно условие.

Пропуск частей for

Любая часть for может быть пропущена.
Например, можно убрать начало. Цикл в примере ниже полностью идентичен приведённому выше:
var i = 0;

for (; i < 3; i++) {
  alert( i ); // 0, 1, 2
}
Можно убрать и шаг:
var i = 0;

for (; i < 3;) {
  alert( i );
  // цикл превратился в аналог while (i<3)
}
А можно и вообще убрать всё, получив бесконечный цикл:
for (;;) {
  // будет выполняться вечно
}
При этом сами точки с запятой ; обязательно должны присутствовать, иначе будет ошибка синтаксиса.

Прерывание цикла: break

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







var sum = 0;

while (true) {

  var value = +prompt("Введите число", '');

  if (!value) break; // (*)

  sum += value;

}
alert( 'Сумма: ' + sum );
Директива break в строке (*), если посетитель ничего не ввёл, полностью прекращает выполнение цикла и передаёт управление на строку за его телом, то есть на alert.
Вообще, сочетание «бесконечный цикл + break» – отличная штука для тех ситуаций, когда условие, по которому нужно прерваться, находится не в начале-конце цикла, а посередине.

Следующая итерация: continue

Директива continue прекращает выполнение текущей итерации цикла.
Она – в некотором роде «младшая сестра» директивы break: прерывает не весь цикл, а только текущее выполнение его тела, как будто оно закончилось.
Её используют, если понятно, что на текущем повторе цикла делать больше нечего.
Например, цикл ниже использует continue, чтобы не выводить чётные значения:


                           for (var i = 0; i < 10; i++) {

  if (i % 2 == 0) continue;

  alert(i);
}
Для чётных i срабатывает continue, выполнение тела прекращается и управление передаётся на следующий проход for.
Директива continue позволяет обойтись без скобок
Цикл, который обрабатывает только нечётные значения, мог бы выглядеть так:
for (var i = 0; i < 10; i++) {

  if (i % 2) {
    alert( i );
  }

}
С технической точки зрения он полностью идентичен. Действительно, вместо continue можно просто завернуть действия в блок if. Однако, мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри ifболее длинный, то это ухудшает читаемость, в отличие от варианта с continue.

 For...in / For...of

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

Цикл for...in проходит только по перечисляемым свойствам. Объекты, созданные встроенными конструкторами, такими как Array и Object имеют неперечисляемые свойства от Object.prototype и String.prototype, например, от String-это indexOf(), а от Object - метод toString(). Цикл пройдёт по всем перечисляемым свойствам объекта, а также тем, что он унаследует от конструктора прототипа (свойства объекта в цепи прототипа).

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

.ForEach()

Метод forEach() выполняет указанную функцию один раз для каждого элемента в массиве.
Метод forEach() выполняет функцию callback один раз для каждого элемента, находящегося в массиве в порядке возрастания. Она не будет вызвана для удалённых или пропущенных элементов массива. Однако, она будет вызвана для элементов, которые присутствуют в массиве и имеют значение undefined.
Функция callback будет вызвана с тремя аргументами:
  • значение элемента (value)
  • индекс элемента (index)
  • массив, по которому осуществляется проход (array)
Если в метод forEach() был передан параметр thisArg, при вызове callback он будет использоваться в качестве значения this. В противном случае, в качестве значения this будет использоваться значение undefined. В конечном итоге, значение this, наблюдаемое из функции callback, определяется согласно обычным правилам определения this, видимого из функции.
Диапазон элементов, обрабатываемых методом forEach(), устанавливается до первого вызова функции callback. Элементы, добавленные в массив после начала выполнения метода forEach(), не будут посещены функцией callback. Если существующие элементы массива изменятся, значения, переданные в функцию callback, будут значениями на тот момент времени, когда метод forEach() посетит их; удалённые элементы посещены не будут.
Примечание: Не существует способа остановить или прервать цикл forEach() кроме как выбрасыванием исключения. Если это требуется, метод forEach() неправильный выбор. Используйте обычные циклы. Если нужно протестировать элементы массива на условие и нужно вернуть булевое значение, вы должны воспользоваться методами Array.prototype.every() или Array.prototype.some().
Метод forEach() выполняет функцию callback один раз для каждого элемента массива; в отличие от методов every() и some(), он всегда возвращает значение undefined.

While / Do...While

Цикл while имеет вид:
while (условие) {
  // код, тело цикла
}
Пока условие верно – выполняется код из тела цикла.

Цикл do…while

Проверку условия можно поставить под телом цикла, используя специальный синтаксис do..while:
do {
  // тело цикла
} while (условие);
Цикл, описанный, таким образом, сначала выполняет тело, а затем проверяет условие.
Например:
var i = 0;
do {
  alert( i );
  i++;
} while (i < 3);
Синтаксис do..while редко используется, т.к. обычный while нагляднее – в нём не приходится искать глазами условие и ломать голову, почему оно проверяется именно в конце.

isNaN()

Функция isNaN() определяет является ли литерал или переменная не числовым значением (NaN) или нет. При работе с функцией необходимо проявлять осторожность так как она работает некорректно. Если вам интересно подробнее можно посмотреть Number.isNaN() то как она описана в ECMAScript 6, в качестве альтернативного решения можно использовать typeof для проверки литерала или переменной на не числовое значение.

parseInt() / parseFloat()

Функция parseInt() принимает строку в качестве аргумента и возвращает целое число в соответствии с указанным основанием системы счисления.

Функция parseFloat() принимает строку в качестве аргумента и возвращает десятичное число (число с плавающей точкой)

toString()

Метод toString() возвращает строку, представляющую объект.

.length

Length свойство объекта, который является экземпляром вида Array , устанавливает или возвращает число элементов в этом массиве. Значение безнаковое 32 битное целое число, которое всегда численно больше чем самый наибольший индекс в массиве.

String

Number

Boolean

Null

Undefined

Object


Symbol