Перейти к содержимому

Что увидит пользователь в случае отсутствия проверки деления на ноль в языке javascript

  • автор:

Методы массивов

Массивы предоставляют множество методов. Чтобы было проще, в этой главе они разбиты на группы.

Добавление/удаление элементов

Мы уже знаем методы, которые добавляют и удаляют элементы из начала или конца:

  • arr.push(. items) – добавляет элементы в конец,
  • arr.pop() – извлекает элемент из конца,
  • arr.shift() – извлекает элемент из начала,
  • arr.unshift(. items) – добавляет элементы в начало.

splice

Как удалить элемент из массива?

Так как массивы – это объекты, то можно попробовать delete :

let arr = ["I", "go", "home"]; delete arr[1]; // удалить "go" alert( arr[1] ); // undefined // теперь arr = ["I", , "home"]; alert( arr.length ); // 3

Элемент был удалён, но в массиве всё ещё три элемента, мы можем увидеть, что arr.length == 3 .

Это естественно, потому что delete obj.key удаляет значение по ключу key . Это всё, что он делает. Хорошо для объектов. Но для массивов мы обычно хотим, чтобы оставшиеся элементы сдвинулись и заняли освободившееся место. Мы ждём, что массив станет короче.

Поэтому нужно использовать специальные методы.

Метод arr.splice(str) – это универсальный «швейцарский нож» для работы с массивами. Умеет всё: добавлять, удалять и заменять элементы.

arr.splice(start[, deleteCount, elem1, . elemN])

Он изменяет arr начиная с индекса start : удаляет deleteCount элементов и затем вставляет elem1, . elemN на их место. Возвращает массив из удалённых элементов.

Этот метод легко понять, рассмотрев примеры.

Начнём с удаления:

let arr = ["Я", "изучаю", "JavaScript"]; arr.splice(1, 1); // начиная с индекса 1, удалить 1 элемент alert( arr ); // осталось ["Я", "JavaScript"]

Легко, правда? Начиная с индекса 1 , он убрал 1 элемент.

В следующем примере мы удалим 3 элемента и заменим их двумя другими.

let arr = ["Я", "изучаю", "JavaScript", "прямо", "сейчас"]; // удалить 3 первых элемента и заменить их другими arr.splice(0, 3, "Давай", "танцевать"); alert( arr ) // теперь ["Давай", "танцевать", "прямо", "сейчас"]

Здесь видно, что splice возвращает массив из удалённых элементов:

let arr = ["Я", "изучаю", "JavaScript", "прямо", "сейчас"]; // удалить 2 первых элемента let removed = arr.splice(0, 2); alert( removed ); // "Я", "изучаю" 

Метод splice также может вставлять элементы без удаления, для этого достаточно установить deleteCount в 0 :

let arr = ["Я", "изучаю", "JavaScript"]; // с индекса 2 // удалить 0 элементов // вставить "сложный", "язык" arr.splice(2, 0, "сложный", "язык"); alert( arr ); // "Я", "изучаю", "сложный", "язык", "JavaScript"

Отрицательные индексы разрешены

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

let arr = [1, 2, 5]; // начиная с индекса -1 (перед последним элементом) // удалить 0 элементов, // затем вставить числа 3 и 4 arr.splice(-1, 0, 3, 4); alert( arr ); // 1,2,3,4,5

slice

Метод arr.slice намного проще, чем похожий на него arr.splice .

arr.slice([start], [end])

Он возвращает новый массив, в который копирует все элементы с индекса start до end (не включая end ). start и end могут быть отрицательными, в этом случае отсчёт позиции будет вестись с конца массива.

Это похоже на строковый метод str.slice , но вместо подстрок возвращает подмассивы.

let arr = ["t", "e", "s", "t"]; alert( arr.slice(1, 3) ); // e,s (копирует с 1 до 3) alert( arr.slice(-2) ); // s,t (копирует с -2 до конца)

Можно вызвать slice без аргументов: arr.slice() создаёт копию arr . Это часто используют, чтобы создать копию массива для дальнейших преобразований, которые не должны менять исходный массив.

concat

Метод arr.concat создаёт новый массив, в который копирует данные из других массивов и дополнительные значения.

arr.concat(arg1, arg2. )

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

В результате – новый массив, включающий в себя элементы из arr , затем arg1 , arg2 и так далее.

Если аргумент argN – массив, то копируются все его элементы. Иначе копируется сам аргумент.

let arr = [1, 2]; // создать массив из: arr и [3,4] alert( arr.concat([3, 4]) ); // 1,2,3,4 // создать массив из: arr и [3,4] и [5,6] alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6 // создать массив из: arr и [3,4], потом добавить значения 5 и 6 alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

Обычно он копирует только элементы из массивов. Другие объекты, даже если они выглядят как массивы, добавляются как есть:

let arr = [1, 2]; let arrayLike = < 0: "что-то", length: 1 >; alert( arr.concat(arrayLike) ); // 1,2,[object Object]

…Но если массивоподобный объект имеет специальное свойство Symbol.isConcatSpreadable , то он обрабатывается как массив, с помощью concat : вместо него добавляются его элементы:

let arr = [1, 2]; let arrayLike = < 0: "что-то", 1: "ещё", [Symbol.isConcatSpreadable]: true, length: 2 >; alert( arr.concat(arrayLike) ); // 1,2,что-то,ещё

Перебор: forEach

Метод arr.forEach позволяет запускать функцию для каждого элемента массива.

arr.forEach(function(item, index, array) < // . делать что-то с item >);

Например, этот код выведет на экран каждый элемент массива:

// Вызов alert для каждого элемента ["Бильбо", "Гэндальф", "Назгул"].forEach(alert);

А этот вдобавок расскажет и о позиции элемента в целевом массиве:

["Бильбо", "Гэндальф", "Назгул"].forEach((item, index, array) => < alert(`У $индекс $ в $`); >);

Результат функции (если она что-то возвращает) отбрасывается и игнорируется.

Поиск в массиве

Теперь рассмотрим методы поиска в массиве.

indexOf/lastIndexOf и includes

У методов arr.indexOf и arr.includes одинаковый синтаксис и они делают по сути то же самое, что и их строковые аналоги, но работают с элементами вместо символов:

  • arr.indexOf(item, from) ищет item начиная с индекса from и возвращает номер индекса, на котором был найден искомый элемент, в противном случае -1 .
  • arr.includes(item, from) ищет item начиная с индекса from и возвращает true , если поиск успешен.

Обычно эти методы используются только с одним аргументом: искомым item . По умолчанию поиск ведется с начала.

let arr = [1, 0, false]; alert( arr.indexOf(0) ); // 1 alert( arr.indexOf(false) ); // 2 alert( arr.indexOf(null) ); // -1 alert( arr.includes(1) ); // true

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

Если мы хотим проверить наличие элемента в массиве и нет необходимости знать его индекс, предпочтительно использовать arr.includes .

Метод arr.lastIndexOf похож на indexOf , но ищет справа налево.

let fruits = ['Яблоко', 'Апельсин', 'Яблоко'] alert( fruits.indexOf('Яблоко') ); // 0 (первый 'Яблоко') alert( fruits.lastIndexOf('Яблоко') ); // 2 (последний 'Яблоко')

Метод includes правильно обрабатывает NaN

Незначительная, но заслуживающая внимания особенность includes – он правильно обрабатывает NaN , в отличие от indexOf :

const arr = [NaN]; alert( arr.indexOf(NaN) ); // -1 (неверно, должен быть 0) alert( arr.includes(NaN) );// true (верно)

Это связано с тем, что includes был добавлен в JavaScript гораздо позже и использует более современный алгоритм сравнения.

find и findIndex/findLastIndex

Представьте, что у нас есть массив объектов. Как нам найти объект с определённым условием?

Здесь пригодится метод arr.find.

let result = arr.find(function(item, index, array) < // если true - возвращается текущий элемент и перебор прерывается // если все итерации оказались ложными, возвращается undefined >);

Функция вызывается по очереди для каждого элемента массива:

  • item – очередной элемент.
  • index – его индекс.
  • array – сам массив.

Если функция возвращает true , поиск прерывается и возвращается item . Если ничего не найдено, возвращается undefined .

Например, у нас есть массив пользователей, каждый из которых имеет поля id и name . Найдем пользователя с id == 1 :

let users = [ , , ]; let user = users.find(item => item.id == 1); alert(user.name); // Вася

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

Обратите внимание, что в данном примере мы передаём find функцию item => item.id == 1 с одним аргументом. Это типично, другие аргументы этой функции используются редко.

У метода arr.findIndex такой же синтаксис, но он возвращает индекс, на котором был найден элемент, а не сам элемент. Значение -1 возвращается, если ничего не найдено.

Метод arr.findLastIndex похож на findIndex , но ищет справа налево, наподобие lastIndexOf .

let users = [ , , , ]; // Найти индекс первого Васи alert(users.findIndex(user => user.name == 'Вася')); // 0 // Найти индекс последнего Васи alert(users.findLastIndex(user => user.name == 'Вася')); // 3

filter

Метод find ищет один (первый) элемент, который заставит функцию вернуть true .

Если найденных элементов может быть много, можно использовать arr.filter(fn).

Синтаксис схож с find , но filter возвращает массив из всех подходящих элементов:

let results = arr.filter(function(item, index, array) < // если `true` -- элемент добавляется к results и перебор продолжается // возвращается пустой массив в случае, если ничего не найдено >);
let users = [ , , ]; // возвращает массив, состоящий из двух первых пользователей let someUsers = users.filter(item => item.id < 3); alert(someUsers.length); // 2

Преобразование массива

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

map

Метод arr.map является одним из наиболее полезных и часто используемых.

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

let result = arr.map(function(item, index, array) < // возвращается новое значение вместо элемента >);

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

let lengths = ["Бильбо", "Гэндальф", "Назгул"].map(item => item.length); alert(lengths); // 6,8,6

sort(fn)

Вызов arr.sort() сортирует массив на месте, меняя в нём порядок элементов.

Он также возвращает отсортированный массив, но обычно возвращаемое значение игнорируется, так как изменяется сам arr .

let arr = [ 1, 2, 15 ]; // метод сортирует содержимое arr arr.sort(); alert( arr ); // 1, 15, 2

Не заметили ничего странного в этом примере?

Порядок стал 1, 15, 2 . Это неправильно. Но почему?

По умолчанию элементы сортируются как строки.

Буквально, элементы преобразуются в строки при сравнении. Для строк применяется лексикографический порядок, и действительно выходит, что "2" > "15" .

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

Функция должна для пары значений возвращать:

function compare(a, b) < if (a >b) return 1; // если первое значение больше второго if (a == b) return 0; // если равны if (a < b) return -1; // если первое значение меньше второго >

Например, для сортировки чисел:

function compareNumeric(a, b) < if (a >b) return 1; if (a == b) return 0; if (a < b) return -1; >let arr = [ 1, 2, 15 ]; arr.sort(compareNumeric); alert(arr); // 1, 2, 15

Теперь всё работает как надо.

Сделаем отступление и подумаем, что происходит. arr может быть массивом чего угодно, верно? Он может содержать числа, строки, объекты или что-то ещё. У нас есть набор каких-то элементов. Чтобы отсортировать его, нам нужна упорядочивающая функция, которая знает, как сравнивать его элементы. По умолчанию элементы сортируются как строки.

Метод arr.sort(fn) реализует общий алгоритм сортировки. Нам не нужно заботиться о том, как он работает внутри (в большинстве случаев это оптимизированная быстрая сортировка или Timsort). Она проходится по массиву, сравнивает его элементы с помощью предоставленной функции и переупорядочивает их. Всё, что нам нужно, – предоставить fn , которая делает сравнение.

Кстати, если мы когда-нибудь захотим узнать, какие элементы сравниваются – ничто не мешает нам вывести их на экран:

[1, -2, 15, 2, 0, 8].sort(function(a, b) < alert( a + " <>" + b ); return a - b; >);

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

Функция сравнения может вернуть любое число

На самом деле от функции сравнения требуется любое положительное число, чтобы сказать «больше», и отрицательное число, чтобы сказать «меньше».

Это позволяет писать более короткие функции:

let arr = [ 1, 2, 15 ]; arr.sort(function(a, b) < return a - b; >); alert(arr); // 1, 2, 15

Лучше использовать стрелочные функции

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

arr.sort( (a, b) => a - b );

Будет работать точно так же, как и более длинная версия выше.

Используйте localeCompare для строк

Помните алгоритм сравнения строк? По умолчанию, он сравнивает буквы по их кодам.

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

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

let countries = ['Österreich', 'Andorra', 'Vietnam']; alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (неправильно) alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (правильно!)

reverse

Метод arr.reverse меняет порядок элементов в arr на обратный.

let arr = [1, 2, 3, 4, 5]; arr.reverse(); alert( arr ); // 5,4,3,2,1

Он также возвращает массив arr с изменённым порядком элементов.

split и join

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

Метод str.split(delim) именно это и делает. Он разбивает строку на массив по заданному разделителю delim .

В примере ниже таким разделителем является строка из запятой и пробела.

let names = 'Вася, Петя, Маша'; let arr = names.split(', '); for (let name of arr) < alert( `Сообщение получат: $.` ); // Сообщение получат: Вася (и другие имена) >

У метода split есть необязательный второй числовой аргумент – ограничение на количество элементов в массиве. Если их больше, чем указано, то остаток массива будет отброшен. На практике это редко используется:

let arr = 'Вася, Петя, Маша, Саша'.split(', ', 2); alert(arr); // Вася, Петя

Разбивка по буквам

Вызов split(s) с пустым аргументом s разбил бы строку на массив букв:

let str = "тест"; alert( str.split('') ); // т,е,с,т

Вызов arr.join(glue) делает в точности противоположное split . Он создаёт строку из элементов arr , вставляя glue между ними.

let arr = ['Вася', 'Петя', 'Маша']; let str = arr.join(';'); // объединить массив в строку через ; alert( str ); // Вася;Петя;Маша

reduce/reduceRight

Когда нам нужно перебрать массив – мы можем использовать forEach , for или for..of .

Когда нам нужно перебрать массив и вернуть данные для каждого элемента – мы можем использовать map .

Методы arr.reduce и arr.reduceRight похожи на методы выше, но они немного сложнее. Они используются для вычисления единого значения на основе всего массива.

let value = arr.reduce(function(accumulator, item, index, array) < // . >, [initial]);

Функция применяется по очереди ко всем элементам массива и «переносит» свой результат на следующий вызов.

  • accumulator – результат предыдущего вызова этой функции, равен initial при первом вызове (если передан initial ),
  • item – очередной элемент массива,
  • index – его позиция,
  • array – сам массив.

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

Так, первый аргумент является по сути аккумулятором, который хранит объединённый результат всех предыдущих вызовов функции. По окончании он становится результатом reduce .

Этот метод проще всего понять на примере.

Тут мы получим сумму всех элементов массива одной строкой:

let arr = [1, 2, 3, 4, 5]; let result = arr.reduce((sum, current) => sum + current, 0); alert(result); // 15

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

Разберём детально как это работает.

  1. При первом запуске sum равен initial (последний аргумент reduce ), то есть 0 , а current – первый элемент массива, равный 1 . Таким образом, результат функции равен 1 .
  2. При втором запуске sum = 1 , к нему мы добавляем второй элемент массива ( 2 ) и возвращаем.
  3. При третьем запуске sum = 3 , к которому мы добавляем следующий элемент, и так далее…

Поток вычислений получается такой:

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

sum current result
первый вызов 0 1 1
второй вызов 1 2 3
третий вызов 3 3 6
четвёртый вызов 6 4 10
пятый вызов 10 5 15

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

Мы также можем опустить начальное значение:

let arr = [1, 2, 3, 4, 5]; // убрано начальное значение (нет 0 в конце) let result = arr.reduce((sum, current) => sum + current); alert( result ); // 15

Результат – точно такой же! Это потому, что при отсутствии initial в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.

Таблица вычислений будет такая же за вычетом первой строки.

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

let arr = []; // Error: Reduce of empty array with no initial value // если бы существовало начальное значение, reduce вернул бы его для пустого массива. arr.reduce((sum, current) => sum + current);

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

Метод arr.reduceRight работает аналогично, но проходит по массиву справа налево.

Array.isArray

Массивы не образуют отдельный тип данных. Они основаны на объектах.

Поэтому typeof не может отличить простой объект от массива:

alert(typeof <>); // object alert(typeof []); // тоже object

…Но массивы используются настолько часто, что для этого придумали специальный метод: Array.isArray(value). Он возвращает true , если value массив, и false , если нет.

alert(Array.isArray(<>)); // false alert(Array.isArray([])); // true

Большинство методов поддерживают «thisArg»

Почти все методы массива, которые вызывают функции – такие как find , filter , map , за исключением метода sort , принимают необязательный параметр thisArg .

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

Вот полный синтаксис этих методов:

arr.find(func, thisArg); arr.filter(func, thisArg); arr.map(func, thisArg); // . // thisArg -- необязательный последний аргумент

Значение параметра thisArg становится this для func .

Например, тут мы используем метод объекта army как фильтр, и thisArg передаёт ему контекст:

let army = < minAge: 18, maxAge: 27, canJoin(user) < return user.age >= this.minAge && user.age < this.maxAge; >>; let users = [ , , , ]; // найти пользователей, для которых army.canJoin возвращает true let soldiers = users.filter(army.canJoin, army); alert(soldiers.length); // 2 alert(soldiers[0].age); // 20 alert(soldiers[1].age); // 23

Если бы мы в примере выше использовали просто users.filter(army.canJoin) , то вызов army.canJoin был бы в режиме отдельной функции, с this=undefined . Это тут же привело бы к ошибке.

Вызов users.filter(army.canJoin, army) можно заменить на users.filter(user => army.canJoin(user)) , который делает то же самое. Последняя запись используется даже чаще, так как функция-стрелка более наглядна.

Итого

Шпаргалка по методам массива:

  • Для добавления/удаления элементов:
    • push(. items) – добавляет элементы в конец,
    • pop() – извлекает элемент с конца,
    • shift() – извлекает элемент с начала,
    • unshift(. items) – добавляет элементы в начало.
    • splice(pos, deleteCount, . items) – начиная с индекса pos удаляет deleteCount элементов и вставляет items .
    • slice(start, end) – создаёт новый массив, копируя в него элементы с индекса start до end (не включая end ).
    • concat(. items) – возвращает новый массив: копирует все члены текущего массива и добавляет к нему items . Если какой-то из items является массивом, тогда берутся его элементы.
    • indexOf/lastIndexOf(item, pos) – ищет item , начиная с позиции pos , и возвращает его индекс или -1 , если ничего не найдено.
    • includes(value) – возвращает true , если в массиве имеется элемент value , в противном случае false .
    • find/filter(func) – фильтрует элементы через функцию и отдаёт первое/все значения, при прохождении которых через функцию возвращается true .
    • findIndex похож на find , но возвращает индекс вместо значения.
    • forEach(func) – вызывает func для каждого элемента. Ничего не возвращает.
    • map(func) – создаёт новый массив из результатов вызова func для каждого элемента.
    • sort(func) – сортирует массив «на месте», а потом возвращает его.
    • reverse() – «на месте» меняет порядок следования элементов на противоположный и возвращает изменённый массив.
    • split/join – преобразует строку в массив и обратно.
    • reduce/reduceRight(func, initial) – вычисляет одно значение на основе всего массива, вызывая func для каждого элемента и передавая промежуточный результат между вызовами.
    • Array.isArray(arr) проверяет, является ли arr массивом.

    Пожалуйста, обратите внимание, что методы push , pop , shift , unshift , sort , reverse и splice изменяют исходный массив.

    Эти методы – самые используемые, их достаточно в 99% случаев. Но существуют и другие:

      arr.some(fn)/arr.every(fn) проверяет массив. Функция fn вызывается для каждого элемента массива аналогично map . Если какие-либо/все результаты вызовов являются true , то метод возвращает true , иначе false . Эти методы ведут себя примерно так же, как операторы || и && : если fn возвращает истинное значение, arr.some() немедленно возвращает true и останавливает перебор остальных элементов; если fn возвращает ложное значение, arr.every() немедленно возвращает false и также прекращает перебор остальных элементов. Мы можем использовать every для сравнения массивов:

    function arraysEqual(arr1, arr2) < return arr1.length === arr2.length && arr1.every((value, index) =>value === arr2[index]); > alert( arraysEqual([1, 2], [1, 2])); // true

    Полный список есть в справочнике MDN.

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

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

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

    Задачи

    Переведите текст вида border-left-width в borderLeftWidth

    важность: 5

    Напишите функцию camelize(str) , которая преобразует строки вида «my-short-string» в «myShortString».

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

    camelize("background-color") == 'backgroundColor'; camelize("list-style-image") == 'listStyleImage'; camelize("-webkit-transition") == 'WebkitTransition';

    P.S. Подсказка: используйте split , чтобы разбить строку на массив символов, потом переделайте всё как нужно и методом join соедините обратно.

    function camelize(str) < return str .split('-') // разбивает 'my-long-word' на массив ['my', 'long', 'word'] .map( // Переводит в верхний регистр первые буквы всех элементом массива за исключением первого // превращает ['my', 'long', 'word'] в ['my', 'Long', 'Word'] (word, index) =>index == 0 ? word : word[0].toUpperCase() + word.slice(1) ) .join(''); // соединяет ['my', 'Long', 'Word'] в 'myLongWord' >

    Основы программирования. Начальный уровень

    Экзамен "Основы программирования. Начальный уровень" для пользователей и системных администраторов.

    • Основы программирования
    • Операторы и функции
    • Базовые понятия
    • Постановка задачи и алгоритмирование
    • Описание
    • Подробнее о товаре
    • Отзывы (0)
    • Вопросы теста
    • Обратная связь

    Форма сдачи теста: Экстерн
    Количество вопросов: 20
    Время: 20 минут.
    Проходной балл: 70%
    Срок действия сертификата: неограничен

    Сертификат появляется в Вашем профиле ресурса GeekBrains, и Вы можете его распечатать.

    GeekBrains

    По наличию 11438 шт.

    Внимание !
    Вопросы к тесту выложены исключительно в ознакомительных целях: количество вопросов может не совпадать с действительным, актуальность не поддерживается,- за решением теста Welcome to the cashier!
    Выберите недопустимое использование команды prompt в языке JavaScript:

    prompt ("this","1");
    prompt("this" 1);
    prompt("thisText",1);

    В какой из "библиотек" в языке JavaScript: находятся математические функции?

    Выберите операции языка JavaScript, возвращающие логический результат:

    Какое значение будет храниться в переменной res , в результате выполнения операторов var res = "str "+ 2 + 2; в языке JavaScript?

    str 4
    "str 2 + 2"
    "str 22"

    Выберите команду в языке JavaScript, при помощи которой пользователь может выводить данные на экран в диалоговом окне:

    Выберите правильную запись присвоения целочисленного значения переменной в языке JavaScript:

    var temp = "1";
    var temp = 1.0;
    var temp = 1;

    Что увидит пользователь в случае отсутствия проверки деления на ноль в языке JavaScript?

    Ошибку
    надпись "Infinity"
    программа не запустится

    Что называют входными данными?

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

    Закончите утверждение: функция в контексте программирования - это

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

    Какой метод в языке JavaScript добавляет элемент в "хвост" массива?

    С какого ключевого слова начинается объявление переменной в языке JavaScript?

    Закончите утверждение:в языке javaScript идентификатор (имя) переменной не может начинаться с .

    символа нижнего подчеркивания "_"
    цифры
    заглавной латинской буквы

    Какое свойство в языке JavaScript показывает количество элементов массива?

    count
    size
    length

    Какое значение будет присвоено переменной res в результате выполнения операторов var res = 2.0 == 2; в языке JavaScript?

    Ничего не будет присвоено. Запись ошибочна
    true
    false

    Выберите правильную запись присвоения логического значения переменной в языке JavaScript:

    var flag = "true";
    var flag = 1;
    var flag = true;

    Закончите утверждение: пустой массив в языке JavaScript инициализируется:

    var arr = [];
    var arr = <>;
    var arr = ();

    Каковы основные свойства алгоритма?

    массовость, результативность, конечность
    функциональность, вложенность, ясность
    общность, многогранность, конечность

    Какова общая цель написания программы?

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

    Что такое ветвление?

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

    Где обычно хранится программа до запуска?

    на жёстком диске или внешнем накопителе
    в оперативной памяти
    в центральном процессоре

    Выберите команду в языке JavaScript, при помощи которой пользователь может вводить данные в программу:

    Что такое алгоритм?

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

    Что означает константа NaN при выполнении арифметических операций в языке JavaScript?

    результат вычисления не является числом
    это простой текст не несущий никакой смысловой нагрузки
    результат вычисления произведён успешно

    Закончите утверждение: все данные, с точки зрения программы, можно разделить на:

    простые и составные
    двоичные и шестнадцатеричные
    входные и выходные

    Что такое переменная?

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

    Закончите утверждение: бит может принимать значения.

    1 и -1
    0 и произвольное число от 1 до 9
    0 и 1

    Какое значение будет присвоено переменной res в результате выполнения операторов var res = true || true && false; в языке JavaScript?

    Ничего не будет присвоено. Запись ошибочна
    False
    true

    Как записывается операция вычисления остатка от деления в целых числах в языке JavaScript?

    Какой тип данных используется в качестве условия в конструкции ветвления?

    логический
    строковый
    числовой

    Закончите утверждение: индексация элементов массива в языке JavaScript начинается с .

    Нуля
    Единицы
    Программист сам задает индексацию

    Как выглядит оператор декремента в языке JavaScript?

    Закончите утверждение: языки программирования можно разделить на

    низкоуровневые и высокоуровневые
    C-подобные и Java-подобные
    языки программирования не имеют никакого разделения

    Как выглядит функция преобразования текста в вещественное число в языке JavaScript?

    parseInt
    parseFloat
    parse

    Закончите утверждение: в качестве исполнителя программы выступает .

    двоичный код
    компьютер
    память

    Какое значение будет присвоено переменной res в результате выполнения операторов var res = 1 > 2 ? 1 : 2; в языке JavaScript?

    1
    2
    Ничего не будет присвоено. Запись ошибочна

    Где программа хранит свои данные после запуска?

    на жёстком диске или внешнем накопителе
    в оперативной памяти
    в центральном процессоре

    Закончите утверждение: программа это –

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

    Необходимо выбрать недопустимое использование команды alert в языке JavaScript:

    alert("this";"Text");
    alert("this"+"Text");
    alert("thisText");

    Укажите неверное утверждение

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

    Как называется базовая единица хранения информации?

    Закончите утверждение: курс "Основы программирования" даёт базовые понятия из области.

    Программирования
    формирования запросов к удалённой системе
    верстки сайтов

    Сколько уникальных значений может принимать 1 байт?

    Закончите утверждение: все данные в компьютере представлены .

    в виде десятичного кода
    в виде двоичного кода
    в виде восьмеричного кода

    Вы можете обратится к нам напрямую, через:

    По Skype: molodoyberkut
    По Telegram: @MolodoyBerkut
    По ICQ: 657089516

    Или через форму обратной связи на нашем сайте

    Сертификат

    • Сертификат

    Получите наши последние новости и специальные предложения

    70 вопросов по JavaScript для подготовки к собеседованию

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

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

    Буду признателен за развернутые комментарии. Все замечания будут учтены при редактировании статьи.

    70 вопросов по JavaScript для подготовки к собеседованию

    1. В чем разница между null и undefined?

    Для начала давайте поговорим о том, что у них общего.

    Во-первых, они принадлежат к 7 «примитивам» (примитивным типам) JS:

    let primitiveTypes = ['string', 'number', 'null', 'undefined', 'boolean', 'symbol', 'bigint'] 

    Во-вторых, они являются ложными значениями, т.е. результатом их преобразования в логическое значение с помощью Boolean() или оператора "!!" является false:

    console.log(!!null) // false console.log(!!undefined) // false console.log(Boolean(null)) // false console.log(Boolean(undefined)) // false 

    Ладно, теперь о различиях.

    • переменной, которой не было присвоено значения, т.е. объявленной, но не инициализированной переменной;
    • функции, которая ничего не возвращает явно, например, console.log(1);
    • несуществующего свойства объекта.
    let _thisIsUndefined const doNothing = () => <> const someObj = < a: 'ay', b: 'bee', c: 'si' >console.log(_thisIsUndefined) // undefined console.log(doNothing()) // undefined console.log(someObj['d']) // undefined 

    null — это «значение отсутствия значения». null — это значение, которое присваивается переменной явно. В примере ниже мы получаем null, когда метод fs.readFile отрабатывает без ошибок:

    fs.readFile('path/to/file', (e, data) => < console.log(e) // здесь мы получаем null if(e) < console.log(e) >console.log(data) >) 

    При сравнении null и undefined мы получаем true, когда используем оператор "==", и false при использовании оператора "== javascript">console.log(null == undefined) // true console.log(null === undefined) // false

    2. Для чего используется оператор "&&"?

    Оператор "&&" (логическое и) находит и возвращает первое ложное значение либо последний операнд, когда все значения истинные. Он использует короткое замыкание во избежание лишних затрат:

    console.log(false && 1 && []) // false console.log(' ' && true && 5) // 5 

    С оператором «if»:

    const router: Router = Router() router.get('/endpoint', (req: Request, res: Response) => < let conMobile: PoolConnection try < // операции с базой данных >catch (e) < if (conMobile) < conMobile.release() >> >) 

    То же самое с оператором "&&":

    const router: Router = Router() router.get('/endpoint', (req: Request, res: Response) => < let conMobile: PoolConnection try < // операции с базой данных >catch (e) < conMobile && conMobile.release() >>) 
    3. Для чего используется оператор "||"?

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

    console.log(null || 1 || undefined) // 1 function logName(name) < let n = name || Mark console.log(n) >logName() // Mark 
    4. Является ли использование унарного плюса (оператор "+") самым быстрым способом преобразования строки в число?

    Согласно MDN оператор "+" действительно является самым быстрым способом преобразования строки в число, поскольку он не выполняет никаких операций со значением, которое является числом.

    5. Что такое DOM?

    DOM или Document Object Model (объектная модель документа) — это прикладной программный интерфейс (API) для работы с HTML и XML документами. Когда браузер первый раз читает («парсит») HTML документ, он формирует большой объект, действительно большой объект, основанный на документе — DOM. DOM представляет собой древовидную структуру (дерево документа). DOM используется для взаимодействия и изменения самой структуры DOM или его отдельных элементов и узлов.

    Допустим, у нас есть такой HTML:

          Document Object Model  

    DOM этого HTML выглядит так:

    В JS DOM представлен объектом Document. Объект Document имеет большое количество методов для работы с элементами, их созданием, модификацией, удалением и т.д.

    6. Что такое распространение события (Event Propagation)?

    Когда какое-либо событие происходит в элементе DOM, оно на самом деле происходит не только в нем. Событие «распространяется» от объекта Window до вызвавшего его элемента (event.target). При этом событие последовательно пронизывает (затрагивает) всех предков целевого элемента. Распространение события имеет три стадии или фазы:

    1. Фаза погружения (захвата, перехвата) — событие возникает в объекте Window и опускается до цели события через всех ее предков.
    2. Целевая фаза — это когда событие достигает целевого элемента.
    3. Фаза всплытия — событие поднимается от event.target, последовательно проходит через всех его предков и достигает объекта Window.

    Подробнее о распространении событий можно почитать здесь и здесь.

    7. Что такое всплытие события?

    Когда событие происходит в элементе DOM, оно затрагивает не только этот элемент. Событие «всплывает» (подобно пузырьку воздуха в воде), переходит от элемента, вызвавшего событие (event.target), к его родителю, затем поднимается еще выше, к родителю родителя элемента, пока не достигает объекта Window.

    Допустим, у нас есть такая разметка:

    function addEvent(el, event, callback, isCapture = false) < if (!el || !event || !callback || typeof callback !== 'function') return if (typeof el === 'string') < el = document.querySelector(el) >el.addEventListener(event, callback, isCapture) > addEvent(document, 'DOMContentLoaded', () => < const child = document.querySelector('.child') const parent = document.querySelector('.parent') const grandparent = document.querySelector('.grandparent') addEvent(child, 'click', function(e) < console.log('child') >) addEvent(parent, 'click', function(e) < console.log('parent') >) addEvent(grandparent, 'click', function(e) < console.log('grandparent') >) addEvent('html', 'click', function(e) < console.log('html') >) addEvent(document, 'click', function(e) < console.log('document') >) addEvent(window, 'click', function(e) < console.log('window') >) >) 

    У метода addEventListener есть третий необязательный параметр — useCapture. Когда его значение равняется false (по умолчанию), событие начинается с фазы всплытия. Когда его значение равняется true, событие начинается с фазы погружения (для «прослушивателей» событий, прикрепленных к цели события, событие находится в целевой фазе, а не в фазах погружения или всплытия. События в целевой фазе инициируют все прослушиватели на элементе в том порядке, в котором они были зарегистрированы независимо от параметра useCapture — прим. пер.). Если мы кликнем по элементу child, в консоль будет выведено: child, parent, grandparent, html, document, window. Вот что такое всплытие события.

    8. Что такое погружение события?

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

    function addEvent(el, event, callback, isCapture = false) < if (!el || !event || !callback || typeof callback !== 'function') return if (typeof el === 'string') < el = document.querySelector(el); >el.addEventListener(event, callback, isCapture) > addEvent(document, 'DOMContentLoaded', () => < const child = document.querySelector('.child') const parent = document.querySelector('.parent') const grandparent = document.querySelector('.grandparent') addEvent(child, 'click', function(e) < console.log('child'); >, true) addEvent(parent, 'click', function(e) < console.log('parent') >, true) addEvent(grandparent, 'click', function(e) < console.log('grandparent') >, true) addEvent('html', 'click', function(e) < console.log('html') >, true) addEvent(document, 'click', function(e) < console.log('document') >, true) addEvent(window, 'click', function(e) < console.log('window') >, true) >) 

    У метода addEventListener есть третий необязательный параметр — useCapture. Когда его значение равняется false (по умолчанию), событие начинается с фазы всплытия. Когда его значение равняется true, событие начинается с фазы погружения. Если мы кликнем по элементу child, то увидим в консоли следующее: window, document, html, grandparent, parent, child. Это и есть погружение события.

    9. В чем разница между методами event.preventDefault() и event.stopPropagation()?

    Метод event.preventDefault() отключает поведение элемента по умолчанию. Если использовать этот метод в элементе form, то он предотвратит отправку формы (submit). Если использовать его в contextmenu, то контекстное меню будет отключено (данный метод часто используется в keydown для переопределения клавиатуры, например, при создании музыкального/видео плеера или текстового редактора — прим. пер.). Метод event.stopPropagation() отключает распространение события (его всплытие или погружение).

    10. Как узнать об использовании метода event.preventDefault()?

    Для этого мы можем использовать свойство event.defaulPrevented, возвращающее логическое значение, служащее индикатором применения к элементу метода event.preventDefault.

    11. Почему obj.someprop.x приводит к ошибке?
    const obj = <> console.log(obj.someprop.x) 

    Ответ очевиден: мы пытается получить доступ к свойству x свойства someprop, которое имеет значение undefined. obj.__proto__.__proto = null, поэтому возвращается undefined, а у undefined нет свойства x.

    12. Что такое цель события или целевой элемент (event.target)?

    Простыми словами, event.target — это элемент, в котором происходит событие, или элемент, вызвавший событие.

    Имеем такую разметку:

     

    И такой простенький JS:

    function clickFunc(event)

    Мы прикрепили «слушатель» к внешнему div. Однако если мы нажмем на кнопку, то получим в консоли разметку этой кнопки. Это позволяет сделать вывод, что элементом, вызвавшим событие, является именно кнопка, а не внешний или внутренние div.

    13. Что такое текущая цель события (event.currentTarget)?

    Event.currentTarget — это элемент, к которому прикреплен прослушиватель событий.

     

    И немного видоизмененный JS:

    function clickFunc(event)

    Мы прикрепили слушатель к внешнему div. Куда бы мы ни кликнули, будь то кнопка или один из внутренних div, в консоли мы всегда получим разметку внешнего div. Это позволяет заключить, что event.currentTarget — это элемент, к которому прикреплен прослушиватель событий.

    14. В чем разница между операторами "==" и "== ==" (абстрактное или нестрогое равенство) и оператором "== ==" производит так называемое неявное сравнение. Оператор "= == https://habrastorage.org/r/w1560/webt/yd/xe/tn/ydxetnfghjtfuex_p-em8v4emck.png" data-src="https://habrastorage.org/webt/yd/xe/tn/ydxetnfghjtfuex_p-em8v4emck.png"/>

    Все примеры возвращают true.

    Первый пример — первое условие алгоритма.
    Второй пример — четвертое условие.
    Третий — второе.
    Четвертый — седьмое.
    Пятый — восьмое.
    И последний — десятое.

    15. Почему результатом сравнения двух похожих объектов является false?
    let a = < a: 1 >let b = < a: 1 >let c = a console.log(a === b) // false console.log(a === c) // true хм. 

    В JS объекты и примитивы сравниваются по-разному. Примитивы сравниваются по значению. Объекты — по ссылке или адресу в памяти, где хранится переменная. Вот почему первый console.log возвращает false, а второй — true. Переменные «a» и «c» ссылаются на один объект, а переменные «a» и «b» — на разные объекты с одинаковыми свойствами и значениями.

    16. Для чего используется оператор "!!"?

    Оператор "!!" (двойное отрицание) приводит значение справа от него к логическому значению.

    console.log(!!null) // false console.log(!!undefined) // false console.log(!!'') // false console.log(!!0) // false console.log(!!NaN) // false console.log(!!' ') // true console.log(!!<>) // true console.log(!![]) // true console.log(!!1) // true console.log(!![].length) // false 
    17. Как записать несколько выражений в одну строку?

    Для этого мы можем использовать оператор "," (запятая). Этот оператор «двигается» слева направо и возвращает значение последнего выражения или операнда.

    let x = 5 x = (x++, x = addFive(x), x *= 2, x -= 5, x += 10) function addFive(num)

    Если мы выведем значение x в консоль, то получим 27. Сначала мы увеличиваем значение x на единицу (x = 6). Затем вызываем функцию addFive() с параметром 6, к которому прибавляем 5 (x = 11). После этого мы умножаем значение x на 2 (x = 22). Затем вычитаем 5 (x = 17). И, наконец, прибавляем 10 (x = 27).

    18. Что такое поднятие (Hoisting)?

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

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

    Контекст выполнения — это среда, в которой выполняется код. Контекст выполнения имеет две фазы — компиляция и собственно выполнение.

    Компиляция. В этой фазе функциональные выражения и переменные, объявленные с помощью ключевого слова «var», со значением undefined поднимаются в самый верх глобальной (или функциональной) области видимости (как бы перемещаются в начало нашего кода. Это объясняет, почему мы можем вызывать функции до их объявления — прим. пер.).

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

    Запомните: поднимаются только функциональные выражения и переменные, объявленные с помощью ключевого слова «var». Обычные функции и стрелочные функции, а также переменные, объявленные с помощью ключевых слов «let» и «const» не поднимаются.

    Предположим, что у нас есть такой код:

    console.log(y) y = 1 console.log(y) console.log(greet('Mark')) function greet(name) < return 'Hello ' + name + '!' >var y 

    Получаем undefined, 1 и 'Hello Mark!'.

    Вот как выглядит фаза компиляции:

    function greet(name) < return 'Hello ' + name + '!' >var y // присваивается undefined // ожидается завершение фазы компиляции // затем начинается фаза выполнения /* console.log(y) y = 1 console.log(y) console.log(greet('Mark')) */ 

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

    Дополнительно о Hoisting можно почитать здесь.

    19. Что такое область видимости (Scope)?

    Область видимости — это место, где (или откуда) мы имеем доступ к переменным или функциям. JS имеем три типа областей видимости: глобальная, функциональная и блочная (ES6).

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

    // глобальное пространство имен var g = 'global' function globalFunc() < function innerFunc() < console.log(g) // имеет доступ к переменной g, поскольку она является глобальной >innerFunc() > 

    Функциональная область видимости (область видимости функции) — переменные, функции и параметры, объявленные внутри функции, доступны только внутри этой функции.

    function myFavouriteFunc(a) < if (true) < var b = 'Hello ' + a >return b > myFavouriteFunc('World') console.log(a) // Uncaught ReferenceError: a is not defined console.log(b) // не выполнится 

    Блочная область видимости — переменные (объявленные с помощью ключевых слов «let» и «const») внутри блока (< >), доступны только внутри него.

    function testBlock() < if (true) < let z = 5 >return z > testBlock() // Uncaught ReferenceError: z is not defined 

    Область видимости — это также набор правил, по которым осуществляется поиск переменной. Если переменной не существует в текущей области видимости, ее поиск производится выше, во внешней по отношению к текущей области видимости. Если и во внешней области видимости переменная отсутствует, ее поиск продолжается вплоть до глобальной области видимости. Если в глобальной области видимости переменная обнаружена, поиск прекращается, если нет — выбрасывается исключение. Поиск осуществляется по ближайшим к текущей областям видимости и останавливается с нахождением переменной. Это называется цепочкой областей видимости (Scope Chain).

    // цепочка областей видимости // внутренняя область видимости -> внешняя область видимости -> глобальная область видимости // глобальная область видимости var variable1 = 'Comrades' var variable2 = 'Sayonara' function outer() < // внешняя область видимости var variable1 = 'World' function inner() < // внутренняя область видимости var variable2 = 'Hello' console.log(variable2 + ' ' + variable1) >inner() > outer() // в консоль выводится 'Hello World', // потому что variable2 = 'Hello' и variable1 = 'World' являются ближайшими // к внутренней области видимости переменными 

    20. Что такое замыкание (Closures)?

    Наверное, это самый сложный вопрос из списка. Я постараюсь объяснить, как я понимаю замыкание.

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

    Примеры — отличный способ объяснить замыкание:

    // глобальная область видимости var globalVar = 'abc' function a() < // область видимости функции console.log(globalVar) >a() // 'abc' // цепочка областей видимости // область видимости функции a -> глобальная область видимости 

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

    Переменная «globalVar» не имеет значения на картинке, потому что ее значение может меняться в зависимости от того, где и когда будет вызвана функция. Но в примере выше globalVar будет иметь значение «abc».

    Теперь пример посложнее:

    var globalVar = 'global' var outerVar = 'outer' function outerFunc(outerParam) < function innerFunc(innerParam) < console.log(globalVar, outerParam, innerParam) >return innerFunc > const x = outerFunc(outerVar) outerVar = 'outer-2' globalVar = 'guess' x('inner') 

    В результате получаем «guess outer inner». Объяснение следующее: когда мы вызываем функцию outerFunc и присваиваем переменной «x» значение, возвращаемое функцией innerFunc, параметр «outerParam» равняется «outer». Несмотря на то, что мы присвоили переменной «outerVar» значение «outer-2», это произошло после вызова функции outerFunc, которая «успела» найти значение переменной «outerVar» в цепочке областей видимости, этим значением было «outer». Когда мы вызываем «x», которая ссылается на innerFunc, значением «innerParam» является «inner», потому что мы передаем это значение в качестве параметра при вызове «x». globalVar имеет значение «guess», потому что мы присвоили ей это значение перед вызовом «x».

    Пример неправильного понимания замыкания.

    const arrFunc = [] for (var i = 0; i < 5; i++) < arrFunc.push(function() < return i >) > console.log(i) // 5 for (let i = 0; i < arrFunc.length; i++) < console.log(arrFunc[i]()) // все 5 >

    Данный код работает не так, как ожидается. Объявление переменной с помощью ключевого слова «var» делает эту переменную глобальной. После добавления функций в массив «arrFunc» значением глобальной переменной «i» становится «5». Поэтому когда мы вызываем функцию, она возвращает значение глобальной переменной «i». Замыкание хранит ссылку на переменную, а не на ее значение во время создания. Эту проблему можно решить, используя IIFE или объявив переменную с помощью ключевого слова «let».

    Подробнее о замыкании можно почитать здесь и здесь.

    21. Какие значения в JS являются ложными?
    const falsyValues = ['', 0, null, undefined, NaN, false] 

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

    22. Как проверить, является ли значение ложным?

    Следует использовать функцию Boolean или оператор "!!" (двойное отрицание).

    23. Для чего используется директива «use strict»?

    «use strict» — это директива ES5, которая заставляет весь наш код или код отдельной функции выполняться в строгом режиме. Строгий режим вводит некоторые ограничения по написанию кода, тем самым позволяя избегать ошибок на ранних этапах.

    Вот какие ограничения накладывает строгий режим.

    Нельзя присваивать значения или обращаться к необъявленным переменным:

    function returnY() < 'use strict' y = 123 return y >returnY() // Uncaught ReferenceError: y is not defined 

    Запрещено присваивать значения глобальный переменным, доступным только для чтения или записи:

    'use strict' var NaN = NaN // Uncaught TypeError: Cannot assign to read only property 'NaN' of object '#' var undefined = undefined var Infinity = 'and beyond' 

    Нельзя удалить «неудаляемое» свойство объекта:

    'use strict' const obj = <> Object.defineProperties(obj, 'x', < value: 1 >) delete obj.x // Uncaught TypeError: Property description must be an object: x 

    Запрещено дублирование параметров:

    'use strict' function someFunc(a, b, b, c) <> // Uncaught SyntaxError: Duplicate parameter name not allowed in this context 

    Нельзя создавать функции с помощью функции eval:

    'use strict' eval('var x = 1') console.log(x) // Uncaught ReferenceError: x is not defined 

    Значением «this» по умолчанию является undefined:

    'use strict' function showMeThis() < return this >showMeThis() // undefined 
    24. Какое значение имеет this?

    Обычно this ссылается на значение объекта, который в данный момент выполняет или вызывает функцию. «В данный момент» означает, что значение this меняется в зависимости от контекста выполнения, от того места, где мы используем this.

    const carDetails = < name: 'Ford Mustang', yearBought: 2005, getName() < return this.name >isRegistered: true > console.log(carDetails.getName()) // Ford Mustang 

    В данном случае метод getName возвращает this.name, а this ссылается на carDetails, объект, в котором выполняется getName, который является ее «владельцем».

    Добавим после console.log три строчки:

    var name = 'Ford Ranger' var getCarName = carDetails.getName console.log(getCarName()) // Ford Ranger 

    Второй console.log выдает Ford Ranger, и это странно. Причина такого поведения заключается в том, что «владельцем» getCarName является объект window. Переменные, объявленные с помощью ключевого слова «var» в глобальной области видимости, записываются в свойства объекта window. this в глобальной области видимости ссылается на объект window (если речь не идет о строгом режиме).

    console.log(getCarName === window.getCarName) // true console.log(getCarName === this.getCarName) // true 

    В этом примере this и window ссылаются на один объект.

    Одним из способов решения данной проблемы является использование методов call или apply:

    console.log(getCarName.apply(carDetails)) // Ford Mustang console.log(getCarName.call(carDetails)) // Ford Mustang 

    Call и apply принимают в качестве первого аргумента объект, который будет являться значением this внутри функции.

    В IIFE, функциях, которые создаются в глобальном области видимости, анонимных функциях и внутренних функциях методов объекта значением this по умолчанию является объект window.

    (function() < console.log(this) >)() // window function iHateThis() < console.log(this) >iHateThis() // window const myFavouriteObj = < guessThis() < function getName() < console.log(this.name) >getName() >, name: 'Marko Polo', thisIsAnnoying(callback) < callback() >> myFavouriteObj.guessThis() // window myFavouriteObj.thisIsAnnoying(function() < console.log(this) // window >) 

    Существует два способа получить «Marko Polo».

    Во-первых, мы можем сохранить значение this в переменной:

    const myFavoriteObj = < guessThis() < const self = this // сохраняем значение this в переменной self function getName() < console.log(self.name) >getName() >, name: 'Marko Polo', thisIsAnnoying(callback) < callback() >> 

    Во-вторых, мы можем использовать стрелочную функцию:

    const myFavoriteObj = < guessThis() < const getName = () => < // копируем значение this из внешнего окружения console.log(this.name) >getName() >, name: 'Marko Polo', thisIsAnnoying(callback) < callback() >> 

    Стрелочные функции не имеют собственного значения this. Они копируют значение this из внешнего лексического окружения.

    25. Что такое прототип объекта?

    В двух словах, прототип — это план (схема или проект) объекта. Он используется как запасной вариант для свойств и методов, существующих в данном объекте. Это также один из способов обмена свойствами и функциональностью между объектами. Это основная концепция прототипного наследования в JS.

    const o = <> console.log(o.toString()) // [object Object] 

    Несмотря на то, что объект «о» не имеет свойства toString, обращение к этому свойству не вызывает ошибки. Если определенного свойства нет в объекте, его поиск осуществляется сначала в прототипе объекта, затем в прототипе прототипа объекта и так до тех пор, пока свойство не будет найдено. Это называется цепочкой прототипов. На вершине цепочки прототипов находится Object.prototype.

    console.log(o.toString === Object.prototype.toString) // true 

    Подробнее о прототипах и наследовании можно почитать здесь и здесь.

    26. Что такое IIFE?

    IIFE или Immediately Invoked Function Expression — это функция, которая вызывается или выполняется сразу же после создания или объявления. Для создания IIFE необходимо обернуть функцию в круглые скобки (оператор группировки), превратив ее в выражение, и затем вызвать ее с помощью еще одних круглых скобок. Это выглядит так: (function()<>)().

    (function( ) < >( )) (function( ) < >)( ) (function named(params) < >)( ) (( ) => < >) (function(global) < >)(window) const utility = (function( ) < return < // утилиты >>) 

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

    Лучшее использование IIFE — это выполнение функций настройки инициализации и предотвращение конфликтов имен с другими переменными в глобальной области видимости (загрязнение глобального пространства имен). Приведем пример.

    У нас есть ссылка на библиотеку somelibrary.js, которая предоставляет некоторые глобальные функции, которые мы можем использовать в нашем коде, но в этой библиотеке есть два метода, createGraph и drawGraph, которые мы не используем, потому что они содержат ошибки. И мы хотим реализовать эти функции самостоятельно.

    Одним из способов решить данную проблему является изменение структуры наших скриптов:

      

    Таким образом, мы переопределяем методы, предоставляемые библиотекой.

    Вторым способом является изменение имен наших функций:

      

    Третий способ — использование IIFE:

      

    В этом примере мы создаем служебную переменную, которая содержит результат IIFE, возвращающий объект, содержащий методы createGraph и drawGraph.

    Вот еще одна проблема, которую можно решить с помощью IIFE:

    val li = document.querySelectorAll('.list-group > li') for (var i - 0, len = li.length; i < len; i++) < li[i].addEventListener('click', function(e) < console.log(i) >) > 

    Допустим, у нас есть элемент «ul» с классом «list-group», содержащий 5 дочерних элементов «li». И мы хотим выводить в консоль значение «i» при клике по отдельному «li». Однако вместо этого в консоль всегда выводится 5. Виной всему замыкание.

    Одним из решений является IIFE:

    var li = document.querySelectorAll('.list-group > li') for (var i = 0, len = li.length; i < len; i++) < (function(currentIndex) < li[currentIndex].addEventListener('click', function(e) < console.log(currentIndex) >) >)(i) > 

    Причина, по которой этот код работает, как задумано, состоит в том, что IIFE создает новую область видимости на каждой итерации, и мы записываем значение «i» в currentIndex.

    27. Для чего используется метод Function.prototype.apply?

    Apply используется для привязки определенного объекта к значению this вызываемой функции.

    const details = < message: 'Hello World!' >function getMessage() < return this.message >getMessage.apply(details) // Hello World! 

    Этот метод похож на Function.prototype.call. Единственное отличие состоит в том, что в apply аргументы передаются в виде массива.

    const person = < name: 'Marko Polo' >function greeting(greetingMessage) < return `$$` > greeting.apply(person, ['Hello']) // Hello Marko Polo 
    28. Для чего используется метод Function.prototype.call?

    Call используется для привязки определенного объекта к значению this вызываемой функции.

    const details = < message: 'Hello World!' >; function getMessage() < return this.message; >getMessage.call(details); // Hello World! 

    Этот метод похож на Function.prototype.apply. Отличие состоит в том, что в call аргументы передаются через запятую.

    const person = < name: 'Marko Polo' >; function greeting(greetingMessage) < return `$$`; > greeting.call(person, 'Hello'); // Hello Marko Polo 
    29. В чем разница между методами call и apply?

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

    const obj1 = < result: 0 >const obj2 = < result: 0 >function reduceAdd() < let result = 0 for (let i = 0, len = arguments.length; i < len; i++) < result += arguments[i] >this.result = result > reduceAdd.apply(obj1, [1, 2, 3, 4, 5]) // 15 reduceAdd.call(obj2, 1, 2, 3, 4, 5) // 15 
    30. Для чего используется метод Function.prototype.bind?

    Bind возвращает новую функцию, значением this которой является объект, указанный в качестве первого параметра. В отличие от bind, call и apply сразу же вызывают функцию.

    import React from 'react' class MyComponent extends React.Component < constructor(props) < super(props) this.state = < value: '' >this.handleChange = this.handleChange.bind(this) // привязываем метод handleChange к компоненту MyComponent > handleChange(e) < // код >render() < return ( < > < input type = < this.props.type >value = < this.state.value >onChange = < this.handleChange >/> ) > > 
    31. Что такое функциональное программирование и какие особенности JS позволяют говорить о нем как о функциональном языке программирования?

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

    Объект Array содержит методы map, filter и reduce, которые являются самыми известными функциями в мире функционального программирования из-за их полезности, а также потому, что они не изменяют массив, что делает эти функции «чистыми». Также в JS имеются замыкание и функции высшего порядка, которые являются характеристиками функционального языка программирования.

    Метод map возвращает новый массив с результатами вызова callback для каждого элемента массива:

    const words = ['Functional', 'Procedural', 'Object-Oriented'] const wordsLength = words.map(word => word.length) 

    Метод filter создает новый массив со всеми элементами, которые удовлетворяют условию, указанному в callback:

    const data = < < name: 'Mark', isRegistered: true > < name: 'Mary', isRegistered: false > < name: 'Mae', isRegistered: true >> const registeredUsers = data.filter(user => user.isRegistered) 

    Метод reduce выполняет callback один раз для каждого элемента массива, за исключением пустот, принимая четыре аргумента: начальное значение (или значение от предыдущего callback), значение текущего элемента, текущий индекс и итерируемый массив:

    const strs = ['I', ' ', 'am', ' ', 'Iron', ' ', 'Man'] const result = strs.reduce((acc, currentStr) => acc + str, '') 
    32. Что такое функции высшего порядка (Higher Order Functions)?

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

    function higherOrderFunction(param, callback)
    33. Почему функции в JS называют объектами первого класса (First-class Objects)?

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

    34. Как бы Вы реализовали метод Array.prototype.map?
    function map(arr, mapCallback) < // проверяем переданные параметры if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') < return [] >else < let result = [] // мы создаем массив с результатами при каждом вызове функции // поскольку мы не хотим менять оригинальный массив for (let i = 0, len = arr.length; i < len; i++) < result.push(mapCallback(arr[i], i, arr)) // помещаем результаты mapCallback в result >return result > > 

    Метод map создает новый массив с результатом вызова указанной функции для каждого элемента массива.

    35. Как бы Вы реализовали метод Array.prototype.filter?
    function filter(arr, filterCallback) < // проверяем передаваемые параметры if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') < return [] >else < let result = [] // . for (let i = 0, len = arr.length; i < len; i++) < // определяем соответствие возвращаемого результата заданному условию if (filterCallback(arr[i], i, arr)) < // помещаем значение, прошедшее фильтр, в result result.push(arr[i]) >> return result > > 

    Метод filter создает новый массив со всеми элементами, прошедшими проверку, задаваемую в передаваемой функции.

    36. Как бы Вы реализовали метод Array.prototype.reduce?
    function reduce(arr, reduceCallbak, initialValue) < // .. if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') < return [] >else < // если в функцию не было передано значения initialValue, то let hasInitialValue = initialValue !== undefined let value = hasInitialValue ? initialValue : arr[0] // мы будем использовать первый элемент initialValue // затем мы перебираем массив, начиная с 1, если в функцию не передавалось значения initialValue, либо с 0, если значение было передано for (let i = hasInitialValue ? 0 : 1, len = arr.length; i < len; i++) < // затем на каждой итерации мы присваиваем результат вызова reduceCallback переменной value = reduceCallback(value, arr[i], i, arr) >return value > > 

    Метод reduce применяет функцию reducer к каждому элементу массива (слева-направо), возвращая одно результирующее значение.

    37. Что такое объект arguments?

    Arguments — это коллекция аргументов, передаваемых функции. Это объект, подобный массиву, у него есть свойство length, мы можем получить доступ к определенному значению с помощью arguments[i], но у него отсутствуют методы forEach, reduce, filter и map. Он позволяет узнать количество параметров функции.

    Преобразовать arguments в массив можно с помощью Array.prototype.slice:

    Array.prototype.slice.call(arguments) 

    Запомните: в стрелочных функциях объект arguments не работает.

    function one() < return arguments >const two = function() < return arguments >const three = function three(< return arguments >) const four = () => arguments four() // arguments is not defined 

    Вызов функции four приводит к ошибке ReferenceError: arguments is not defined. Эту проблему можно решить с помощью оператора rest:

    const four = (. args) => args 

    Это автоматически поместит все параметры в массив.

    38. Как создать объект, не имеющий прототипа?

    Это можно сделать с помощью Object.create:

    const o1 = <> console.log(o1.toString) // [object Object] const o2 = Object.create(null) // в качестве первого параметра методу Object-create передается объект-прототип // нам не нужен объект-прототип, поэтому передаем null console.log(o2.toString) // o2.toString is not a function 
    39. Почему в представленном коде переменная b становится глобальной при вызове функции?
    function myFunc() < let a = b = 0 >myFunc() 

    Так происходит, потому что оператор присваивания (" javascript">function myFunc() < let a = (b = 0) >myFunc()

    Сначала значение 0 присваивается переменной «b», которая не объявлена. Движок JS делает ее глобальной. Возвращаемое выражением b = 0 значение (0) затем присваивается локальной переменной «a».

    Эту проблему можно решить сначала объявив локальные переменные, а затем присвоив им значения:

    function myFunc() < let a, b a = b = 0 >myFunc() 
    40. Что такое ECMAScript?

    ECMAScript — это спецификация, стандарт скриптовых языков программирования, он является основой JS, поэтому любые изменения ECMAScript отражаются на JS.

    Последний вариант спецификации ECMA-262 можно посмотреть здесь.

    41. Что нового привнес в JS стандарт ES6 или ECMAScript2015?
    • Стрелочные функции (Arrow Functions).
    • Классы (Classes).
    • Шаблонные строки (Template Strings).
    • Расширенные объектные литералы (Enhanced Object literals).
    • Деструктуризация (Object Destructuring).
    • Промисы (Promises).
    • Генераторы (Generators).
    • Модули (Modules).
    • Symbol.
    • Прокси (Proxies).
    • Множества (Sets).
    • Параметры по умолчанию.
    • Операторы rest и spread.
    • Блочная область видимости (ключевые слова «let» и «const»).
    42. В чем разница между ключевыми словами «var», «let» и «const»?

    Переменные, объявленные с помощью ключевого слова «var», являются глобальными. Это означает, что они доступны из любого места в коде:

    function giveMeX(showX) < if(showX)< var x = 5 >return x > console.log(giveMeX(false)) console.log(giveMeX(true)) 

    Результатом первого console.log будет undefined, второго — 5. Мы имеем доступ к переменной «x» из-за ее всплытия в глобальную область видимости. Код из примера выше интерпретируется следующим образом:

    function giveMeX(showX) < var x // имеет значение undefined if(showX)< x = 5 >return x > 

    Результатом первого console.log является undefined, поскольку объявленные переменные, которым не присвоено значения, имеют значение undefined по умолчанию.

    Переменные, объявленные с помощью ключевых слов «let» и «const» имеют блочную область видимости. Это означает, что они доступны только внутри блока (< >):

    function giveMeX(showX) < if(showX)< let x = 5 >return x > function giveMeY(showY) < if(showY)< let y = 5 >return y > 

    Вызов этих функций с параметром false приведет к ошибке ReferenceError, потому что к переменным «x» и «y» нет доступа снаружи блока и их значения не возвращаются (не всплывают).

    Разница между «let» и «const» состоит в том, что в первом случае мы может менять значение переменной, а во втором — нет (константа). При этом, мы можем менять значение свойства объекта, объявленного с помощью const, но не само свойство (переменную).

    43. Что такое стрелочные функции (Arrow Functions)?

    Стрелочная функция — это относительно новый способ создания функций в JS. Стрелочные функции создаются быстрее и имеют более читаемый синтаксис, чем функциональные выражения. В стрелочных функциях опускается слово «function»:

    // ES5 var getCurrentDate = function() < return new Date() >// ES6 const getCurrentDate = () => new Date() 

    В функциональном выражении мы используем ключевое слово «return» для возврата значения. В стрелочной функции мы этого не делаем, поскольку стрелочные функции неявно возвращают значения при условии, что мы возвращаем одно выражение или значение:

    // ES5 function greet(name) < return 'Hello ' + name + '!' >// ES6 const greet = (name) => `Hello $` const greet2 = name = > `Hello $` 

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

    const getArgs = () => arguments const getArgs2 = (. rest) => rest 

    У стрелочных функций нет доступа к объекту arguments. Поэтому вызов первой функции приведет к ошибке. Для получения параметров, переданных функции, мы можем использовать оператор rest.

    const data = < result: 0 nums: [1,2,3,4,5] computeResult()< // this ссылается на объект data const addAll = () => < // стрелочные функции копируют значение this из лексического окружения return this.nums.reduce((total, cur) =>total + cur, 0) > this.result = addAll() > > 
    44. Что такое классы (Classes)?

    Классы — это относительно новый способ написания функций-конструкторов в JS. Это синтаксический сахар для функций-конструкторов. В основе классов лежат те же прототипы и прототипное наследование:

    // ES5 function Person(firstName, lastName, age, address) < this.firstName = firstName this.lastName = lastName this.age = age this.address = address >Person.self = function() < return this >Person.prototype.toString = function() < return '[object Person]' >Person.prototype.getFullName = function() < return this.firstName + ' ' + this.lastName >// ES6 class Person < constructor(firstName, lastName, age, address)< this.firstName = firstName this.lastName = lastName this.age = age this.address = address >static self() < return this >toString() < return '[object Person]' >getFullName() < return `$$` > > 

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

    // ES5 Employee.prototype = Object.create(Person.prototype) function Employee(firstName, lastName, age, address, jobTitle, yearStarted) < Person.call(this, firstName, lastName, age, address) this.jobTitle = jobTitle this.yearStarted = yearStarted >Employee.prototype.describe = function() < return `I am $and I have a position of # and I started at $>` > Employee.prototype.toString = function() < return '[object Employee]' >// ES6 class Employee extends Person < // наследуемся от Person constructor(firstName, lastName, age, address, jobTitle, yearStarted)< super(firstName, lastName, age, address) this.jobTitle = jobTitle this.yearStarted = yearStarted >describe() < return `I am $and I have a position of # and I started at $>` > toString() < // переопределяем метод toString класса Person return '[object Employee]' >> 

    Как узнать об использовании прототипов?

    class Something < >function AnotherSomething() < >const as = new AnotherSomething() const s = new Something() console.log(typeof Something) // function console.log(typeof AnotherSomething) // function console.log(as.toString()) // [object Object] console.log(a.toString()) // [object Object] console.log(as.toString === Object.prototype.toString) console.log(a.toString === Object.prototype.toString) // в обоих случаях получаем true // Object.prototype находится на вершине цепочки прототипов // Something и AnotherSomething наследуют от Object.prototype 
    45. Что такое шаблонные литералы (Template Literals)?

    Шаблонные литералы — относительно новый способ создания строк в JS. Шаблонные литералы создаются с помощью двойных обратных кавычек (``):

    // ES5 var greet = 'Hi I\'m Mark' // ES6 let greet = `Hi I'm Mark` 

    В шаблонных литералах нам не нужно экранировать одинарные кавычки.

    // ES5 var lastWords = '\n' + ' I \n' + ' am \n' + 'Iron Man \n' // ES6 let lastWords = ` I am Iron Man ` 

    В ES6 нам не нужно использовать управляющую последовательность "\n" для перевода строки.

    // ES5 function greet(name) < return 'Hello ' + name + '!' >// ES6 function greet(name)< return `Hello $!` > 

    В ES6 нам не нужно использовать конкатенацию строк для объединения текста с переменной: мы можем использовать выражение $ для получения значения переменной.

    46. Что такое деструктуризация объекта (Object Destructuring)?

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

    Допустим, у нас есть такой объект:

    const employee =

    Раньше для получения свойств объекта мы создавали переменные для каждого свойства. Это было очень скучно и сильно раздражало:

    var firstName = employee.firstName var lastName = employee.lastName var position = employee.position var yearHired = employee.yearHired 

    Использование деструктуризации позволяет сделать код чище и отнимает меньше времени. Синтаксис деструктуризации следующий: заключаем свойства объекта, которые хотим получить, в фигурные скобки (< >), а если речь идет о массиве — в квадратные скобки ([ ]):

    let < firstName, lastName, position, yearHired >= employee 

    Для изменения имени переменной следует использовать «propertyName: newName»:

    let < firstName: fName, lastName: lName, position, yearHired >= employee 

    Для присвоения переменным значения по умолчанию следует использовать «propertyName = 'defaultValue'»:

    let < firstName = 'Mark', lastName: lName, position, yearHired >= employee 
    47. Что такое модули (Modules)?

    Модули позволяют объединять (использовать) код из разных файлов и избавляют нас от необходимости держать весь код в одном большом файле. До появления модулей в JS существовало две популярные системы модулей для поддержки кода:

    • CommonJS — Nodejs
    • AMD (AsyncronousModuleDefinition) — Browsers

    Экспорт функциональности в другой файл (именной экспорт):

    // ES5 CommonJS - helpers.js exports.isNull = function(val) < return val === null >exports.isUndefined = function(val) < return val === undefined >exports.isNullOrUndefined = function(val) < return exports.isNull(val) || exports.isUndefined(val) >// ES6 модули export function isNull(val) < return val === null; >export function isUndefined(val) < return val === undefined; >export function isNullOrUndefined(val)

    Импорт функциональности в другой файл:

    // ES5 CommonJS - index.js const helpers = require('./helpers.js') const isNull = helpers.isNull const isUndefined = helpers.isUndefined const isNullOrUndefined = helpers.isNullOrUndefined // либо с помощью деструктуризации const < isNull, isUndefined, isNullOrUndefined >= require('./helpers.js') // ES6 модули import * as helpers from './helpers.js' // helpers - это объект // либо import < isNull, isUndefined, isNullOrUndefined as isValid>from './helpers.js' // используем "as" для переименовывания 

    Экспорт по умолчанию:

    // ES5 CommonJS - index.js class Helpers < static isNull(val)< return val === null >static isUndefined(val) < return val === undefined >static isNullOrUndefined(val) < return this.isNull(val) || this.isUndefined(val) >> module.exports = Helpers // ES6 модули class Helpers < static isNull(val)< return val === null >static isUndefined(val) < return val === undefined >static isNullOrUndefined(val) < return this.isNull(val) || this.isUndefined(val) >> export default Helpers 
    // ES5 CommonJS - index.js const Helpers = require('./helpers.js') console.log(Helpers.isNull(null)) // ES6 модули import Helpers from './helpers.js' console.log(Helpers.isNull(null)) 

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

    48. Что такое объект Set?

    Объект Set позволяет хранить уникальные значения, примитивы и ссылки на объекты. Еще раз: в Set можно добавлять только уникальные значения. Он проверяет хранящиеся в нем значения с помощью алгоритма SameZeroValue.

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

    const set1 = new Set() const set2 = new Set(['a','b','c','d','d','e']) // вторая "d" не добавится 

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

    set2.add('f') set2.add('g').add('h').add('i').add('j').add('k').add('k') // вторая "k" не добавится 

    Мы можем удалять значения из Set, используя метод delete:

    set2.delete('k') // true set2.delete('z') // false, потому что в set2 нет такого значения 

    Мы можем проверить наличие свойства в Set, используя метод has:

    set2.has('a') // true set2.has('z') // false 

    Для получения длины Set используется метод size:

    set2.size // 10 

    Метод clear очищает Set:

    set2.clear() // пусто 

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

    const nums = [1,2,3,4,5,6,6,7,8,8,5] const uniqNums = [. new Set(nums)] // [1,2,3,4,5,6,7,8] 
    49. Что такое функция обратного вызова (Callback Function)?

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

    const btnAdd = document.getElementById('btnAdd') btnAdd.addEventListener('click', function clickCallback(e)) < // делаем нечто полезное >

    В примере мы ждем события «клик» на элементе с идентификатором «btnAdd». По клику вызывается функция clickCallback. Функция обратного вызова добавляет некоторый функционал данным или событию. Методам reduce, filter и map в качестве второго аргумента передается функция обратного вызова. Хорошей аналогией callback является следующая ситуация: Вы звоните кому-то, он не отвечает, Вы оставляете ему сообщение и ждете, когда он перезвонит. Звонок или сообщение — это событие или данные, а callback — это ожидание (предвосхищение) встречного звонка.

    50. Что такое промисы (Promises)?

    Промисы — это один из приемов работы с асинхронным кодом в JS. Они возвращают результат асинхронной операции. Промисы были придуманы для решения проблемы так называемого «ада функций обратного вызова».

    fs.readFile('somefile.txt', function(e, data) < if(e)< console.log(e) >console.log(data) >) 

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

    fs.readFile('somefile.txt', function(e,data)< // код fs.readFile('directory', function(e, files)< // код fs.mkdir('directory', function(e)< // код >) >) >) 

    А вот как это выглядит с промисами:

    promReadFile('file/path') .then(data => < return promReaddir('directory') >) .then(data => < return promMkdir('directory') >) .catch(e => < console.error(e) >) 

    У промиса есть четыре состояния:

    • Ожидание — начальное состояние промиса. Результата промиса неизвестен, поскольку операция не завершена.
    • Выполнено — асинхронная операция выполнена, имеется результат.
    • Отклонено — асинхронная операция не выполнена, имеется причина.
    • Завершено — выполнено или отклонено.
    const myPromiseAsync = (. args) => < return new Promise((resolve, reject) => < doSomeAsync(. args, (error, data) => < if(error)< reject(error) >else < resolve(data) >>) >) > myPromiseAsync() .then(result => < console.log(result) >) .catch(reason => < console.error(reason) >) 

    Мы можем создать вспомогательную функцию для преобразования асинхронной операции с callback в промис. Она будет работать наподобие util из Node.js («промисификация»):

    const toPromise = (asyncFuncWithCallback) => < return (. args) => < return new Promise((res, rej) => < asyncFuncWithCallback(. args, (e, result) =>< return e ? rej(e) : res(result) >) >) > > const promiseReadFile = toPromise(fs.readFile) promiseReadFile('file/path') .then((data) => < console.log(data) >) .catch(e => console.error(e)) 

    Подробнее о промисах можно почитать здесь и здесь.

    51. Что такое async/await?

    Async/await — относительно новый способ написания асинхронного (неблокирующего) кода в JS. Им оборачивают промис. Он делает код более читаемым и чистым, чем промисы и функции обратного вызова. Однако для использования async/await необходимо хорошо знать промисы.

    // промис function callApi() < return fetch('url/to/api/endpoint') .then(resp =>resp.json()) .then(data => < // работаем с данными >).catch(err => < // работаем с ошибкой >) > // async/await // для перехвата ошибок используется try/catch async function callApi() < try< const resp = await fetch('url/to/api/endpoint') const data = await res.json() // работаем с данными >catch(e) < // работаем с ошибкой >> 

    Запомните: использование ключевого слова «async» перед функцией заставляет ее возвращать промис:

    const giveMeOne = async () = 1 giveMeOne() .then((num) => < console.log(num) // 1 >) 

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

    const giveMeOne = async() => 1 function getOne() < try< const num = await giveMeOne() console.log(num) >catch(e) < console.log(e) >> // Uncaught SyntaxError: await is only valid in an async function async function getTwo() < try< const num1 = await giveMeOne() const nm2 = await giveMeOne() return num1 + num2 >catch(e) < console.log(e) >> await getTwo() // 2 

    Подробнее об async/await можно почитать здесь и здесь.

    52. В чем разница между spread-оператором и rest-оператором?

    Операторы spread и rest имеют одинаковый синтаксис (". "). Разница состоит в том, что с помощью spread мы передаем или распространяем данные массива на другие данные, а с помощью rest — получаем все параметры функции и помещаем их в массив (или извлекаем часть параметров).

    function add(a, b) < return a + b >const nums = [5, 6] const sum = add(. nums) console.log(sum) // 11 

    В этом примере мы используем spread при вызове функции add с данными массива nums. Значением переменной «a» будет 5, b = 6, sum = 11.

    function add(. rest) < return rest.reduce((total, current) =>total + current) > console.log(add(1, 2)) // 3 console.log(add(1, 2, 3, 4, 5)) // 15 

    Здесь мы вызываем функцию add с любым количеством аргументов. Add возвращает сумму этих аргументов.

    const [first, . others] = [1, 2, 3, 4, 5] console.log(first) // 1 console.log(others) // [2, 3, 4, 5] 

    В этом примере мы используем rest для помещения любого количества параметров, кроме первого, в массив others.

    53. Что такое параметры по умолчанию (Default Parameters)?

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

    // ES5 function add(a,b) < a = a || 0 b = b || 0 return a + b >// ES6 function add(a = 0, b = 0) < return a + b >// если мы не присвоим переменным "a" и "b" какие-нибудь значения, они будут равняться 0 add(1) // 1 

    Можно использовать деструктуризацию:

    function getFirst([first, . rest] = [0, 1]) < return first >getFirst() // 0 getFirst([10,20,30]) // 10 function getArr( < nums >= < nums: [1,2,3,4] >) < return nums >getArr // [1,2,3,4] getArr() // [5,4,3,2,1] 

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

    function doSomethingWithValue(value = 'Hello World', callback = () => < console.log(value) >) < callback() >doSomethingWithValue() // Hello World 
    54. Что такое объектная обертка (Wrapper Objects)?

    Примитивы строка, число и boolean имеют свойства и методы, несмотря на то, что они не являются объектами:

    let name = 'marko' console.log(typeof name) // string console.log(name.toUpperCase()) // MARKO 

    Name — это строка (примитивный тип), у которого нет свойств и методов, но когда мы вызываем метод toUpperCase(), это приводит не к ошибке, а к «MARKO».

    Причина такого поведения заключается в том, что name временно преобразуется в объект. У каждого примитива, кроме null и undefined, есть объект-обертка. Такими объектами являются String, Number, Boolean, Symbol и BigInt. В нашем случае код принимает следующий вид:

    console.log(new String(name).toUpperCase()) // MARKO 

    Временный объект отбрасывается по завершении работы со свойством или методом.

    55. В чем разница между явным и неявным преобразованием или приведением к типу (Implicit and Explicit Coercion)?

    Неявное преобразование — это способ приведения значения к другому типу без нашего ведома (участия).

    Предположим, у нас есть следующее:

    console.log(1 + '6') console.log(false + true) console.log(6 * '2') 

    Результатом первого console.log будет 16. В других языках это привело бы к ошибке, но в JS 1 конвертируется в строку и конкатенируется (присоединяется) c 6. Мы ничего не делали, преобразование произошло автоматически.

    Результатом второго console.log будет 1. False было преобразовано в 0, true — в 1. 0 + 1 = 1.

    Результатом третьего console.log будет 12. Строка 2 была преобразована в число перед умножением на 6.

    Явное преобразование предполагает наше участие в приведении значения к другому типу:

    console.log(1 + parseInt('6')) 

    В этом примере мы используем parseInt для приведения строки 6 к числу, затем складываем два числа и получаем 7.

    56. Что такое NaN? Как проверить, является ли значение NaN?

    NaN или Not A Number (не число) — это значение, получаемое в результате выполнения числовой операции над нечисловым значением:

    let a console.log(parseInt('abc')) console.log(parseInt(null)) console.log(parseInt(undefined)) console.log(parseInt(++a)) console.log(parseInt(<> * 10)) console.log(parseInt('abc' - 2)) console.log(parseInt(0 / 0)) console.log(parseInt('10a' * 10)) 

    В JS есть встроенный метод isNaN, позволяющий проверять, является ли значение NaN, но он ведет себя довольно странно:

    console.log(isNaN()) // true console.log(isNaN(undefined)) // true console.log(isNaN(<>)) // true console.log(isNaN(String('a'))) // true console.log(isNaN(() => < >)) // true 

    Результатом всех console.log является true, несмотря на то, что ни одно из значений не является NaN.

    ES6 для проверки, является ли значение NaN, рекомендует использовать метод Number.isNaN. Мы также можем написать вспомогательную функцию для решения проблемы «неравенства NaN самому себе»:

    function checkIsNan(value)
    57. Как проверить, является ли значение массивом?

    Для этого следует использовать метод Array.isArray:

    console.log(Array.isArray(5)) // false console.log(Array.isArray('')) // false console.log(Array.isArray()) // false console.log(Array.isArray(null)) // false console.log(Array.isArray( )) // false console.log(Array.isArray([])) // true 

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

    function isArray(value)
    58. Как проверить, что число является четным, без использования деления по модулю или деления с остатком (оператора "%")?

    Для решения данной задачи можно использовать оператор "&" (бинарное и). Оператор "&" сравнивает операнды как бинарные значения.

    function isEven(num) < if(num & 1)< return false >else < return true >> 

    0 в бинарной системе счисления это 000
    1 — это 001
    2 — 010
    3 — 011
    4 — 100
    5 — 101
    6 — 110
    7 — 111
    и т.д.

    Console.log(5 & 1) вернет 1. Сначала оператор "&" конвертирует оба числа в бинарные значения, 5 превращается в 101, 1 — в 001. Затем производится побитовое сравнение:

    Сравниваем 1 и 0, получаем 0.
    Сравниваем 0 и 0, получаем 0.
    Сравниваем 1 и 1, получаем 1.
    Преобразуем бинарное значение в целое число, получаем 1.

    Если эта информация кажется Вам слишком сложной, мы можем решить поставленную задачу с помощью рекурсивной функции:

    function isEven(num)
    59. Как определить наличие свойства в объекте?

    Существует три способа это сделать.

    Первый способ состоит в использовании оператора «in»:

    const o = < 'prop': 'bwahahah', 'prop2': 'hweasa' >console.log('prop' in o) // true console.log('prop1' in o) // false 

    Второй — использовать метод hasOwnProperty:

    console.log(o.hasOwnProperty('prop2')) // true console.log(o.hasOwnProperty('prop1')) // false 

    Третий — индексная нотация массива:

    console.log(o['prop']) // bwahahah console.log(o['prop1']) // undefined 
    60. Что такое AJAX?

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

    AJAX использует следующие технологии:
    HTML — структура веб-страницы.
    CSS — стили веб-страницы.
    JavaScript — поведение страницы и работа с DOM.
    XMLHttpRequest API — отправка и получение данных с сервера.
    PHP, Python, Nodejs — какой-нибудь серверный язык.

    61. Как в JS создать объект?
    const o = < name: 'Mark', greeting()< return `Hi, I'm $` > > o.greeting // Hi, I'm Mark 
    function Person(name) < this.name = name >Person.prototype.greeting = function()< return `Hi, I'm $` > const mark = new Person('Mark') mark.greeting() // Hi, I'm Mark 
    const n = < greeting()< return `Hi, I'm $` > > const o = Object.create(n) o.name = 'Mark' console.log(o.greeting) // Hi, I'm Mark 
    62. В чем разница между методами Object.freeze и Object.seal?

    Разница заключается в том, что при использовании метода Object.freeze мы не можем менять или редактировать свойства объекта, а при использовании Object.seal у нас такая возможность имеется.

    63. В чем разница между оператором «in» и методом hasOwnProperty?

    Отличие состоит в том, что оператор «in» проверяет наличие свойства не только в самом объекте, но и в его прототипах, а метод hasOwnProperty — только в объекте.

    console.log('prop' in o) // true console.log('toString' in o) // true console.log(o.hasOwnProperty('prop')) // true console.log(o.hasOwnProperty('toString')) // false 
    64. Какие приемы работы с асинхронным кодом в JS Вы знаете?
    • Функции обратного вызова (Callbacks).
    • Промисы (Promises).
    • Async/await.
    • Библиотеки вроде async.js, blueprint, q, co.
    65. В чем разница между обычной функцией и функциональным выражением?

    Допустим, у нас есть следующее:

    hoistedFunc() notHoistedFunc() function hoistedFunc() < console.log('I am hoisted') >var notHoistedFunc = function()

    Вызов notHoistedFunc приведет к ошибке, а вызов hoistedFunc нет, потому что hoistedFunc «всплывает», поднимается в глобальную область видимости, а notHoistedFunc нет.

    66. Как в JS вызвать функцию?

    В JS существует 4 способа вызвать функцию. Вызов определяет значение this или «владельца» функции.

    Вызов в качестве функции. Если функция вызывается как метод, конструктор или с помощью методов apply или call, значит она вызывается как функция. Владельцем такой функции является объект window:

    function add(a,b) < console.log(this) return a + b >add(1,5) // window, 6 const o = < method(callback)< callback() >> o.method(function()< console.log(this) // window >) 

    Вызов в качестве метода. Когда функция является свойством объекта, мы называем ее методом. Когда вызывается метод, значением this становится объект этого метода:

    const details = < name: 'Marko', getName()< return this.name >> details.getName() // Marko, значением this является объект details 

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

    function Employee(name, position, yearHired) < // создается пустой объект, являющийся значением this // this = <>this.name = name this.position = position this.yearHired = yearHired // наследование от Employee.prototype неявно возвращает this, если не указано иное > const emp = new Employee('Marko Polo', 'Software Development', 2017) 

    Вызов с помощью методов apply или call. Мы используем эти методы, когда хотим явно определить значение this или владельца функции:

    const obj1 = < result: 0 >const obj2 = < result: 0 >function reduceAdd() < let result = 0 for(let i = 0, len = arguments.length; i < len; i++)< result += arguments[i] >this.result = result > reduceAdd.apply(obj1, [1,2,3,4,5]) // значением this является obj1 reduceAdd.call(obj2, 1,2,3,4,5) // значением this является obj2 
    67. Что такое запоминание или мемоизация (Memoization)?

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

    68. Как бы Вы реализовали вспомогательную функцию запоминания?
    function memoize(fn) < const cache = <>return function(param) < if(cache[param])< console.log('cached') return cache[param] >else < let result = fn(param) cache[param] = result console.log('not cached') return result >> > const toUpper = (str = '') => str.toUpperCase() const toUpperMemoized = memoize(toUpper) toUpperMemoized('abcdef') toUpperMemoized('abcdef') // не выполнится 

    Мы реализовали функцию мемоизации с одним аргументом. Сделаем ее «мультиаргументной»:

    const slice = Array.prototype.slice function memoize(fn) < const cache = <>return (. args) => < const params = slice.call(args) console.log(params) if(cache[params])< console.log('cached') return cache[params] >else < let result = fn(. args) cache[params] = result console.log('not cached') return result >> > const makeFullName = (fName, lName) => `$ $` const reduceAdd = (numbers, startValue = 0) => numbers.reduce((total, cur) => total + cur, startValue) const memoizedFullName = memoize(makeFullName) const memoizeReduceAdd = memoize(reduceAdd) memoizedFullName('Marko', 'Polo') memoizedFullName('Marko', 'Polo') // не выполнится memoizeReduceAdd([1,2,3,4],5) memoizeReduceAdd([1,2,3,4],5) // не выполнится 
    69. Почему typeof null возвращает object? Как проверить, является ли значение null?

    typeof null == 'object' всегда будет возвращать true по историческим причинам. Поступало предложение исправить эту ошибку, изменив typeof null = 'object' на typeof null = 'null', но оно было отклонено в интересах сохранения обратной совместимости (такое изменение повлекло бы за собой большое количество ошибок).

    Для проверки, является ли значение null можно использовать оператор строгого равенства (===):

    function isNull(value)
    70. Для чего используется ключевое слово «new»?

    Ключевое слово «new» используется в функциях-конструкторах для создания нового объекта (нового экземпляра класса).

    Допустим, у нас есть такой код:

    function Employee(name, position, yearHired) < this.name = name this.position = position this.yearHired = yearHired >const emp = new Employee('Marko Polo', 'Software Development', 2017) 

    Ключевое слово «new» делает 4 вещи:

    1. Создает пустой объект.
    2. Привязывает к нему значение this.
    3. Функция наследует от functionName.prototype.
    4. Возвращает значение this, если не указано иное.
    • javascript
    • программирование
    • разработка

    df-zz-ns / JS_webformyself.js

    This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

    /* функции */
    /* функции вывода */
    alert ( ) ;
    document . write ( "hello" ) ;
    typeof
    isNaN ( myVar ) ;
    isFinite ( myVar ) ;
    //
    // массивы
    length ;
    for in
    reverse ( ) ;
    join ( ) ;
    sort ( ) ;
    concat ( ) ;
    slice ( ) ;
    splice ( ) ;
    push ( ) ;
    pop ( ) ;
    unshift ( ) ;
    shift ( ) ;
    оператор delete
    инструкция in
    Array . isArray ( ) ;
    //
    // функции
    function max ( )
    var arr = arguments ;
    >
    //
    //
    // Объекты
    var obj =
    delete obj . prop ; // удаление свойства. Только у данного объекта, в свойства прототипа он не лезет.
    var obj2 = Object . create ( obj1 ) ; // создать прототип для obj2
    obj . hasOwnProperty ( 'prop' ) ; // проверить есть ли свойство в объекте. true or false.Вернет false, если свойство наследуется
    console . log ( 'prop1' in obj ) ; // --|-- Вернет true, если свойсто есть, независимо наследуется или нет.
    //
    //
    // window
    setTimeout ( 'func()' , 1000 ) ;
    setInterval ( 'fucn()' , 1000 ) ;
    w = window . open ( 'http://ya.ru' , 'mywindow' , 'width=100,height=100,menubar=1,toolbar=1,resizable=0,scrollbars=0' ) ;
    w . close ( ) ;
    w . focus ( ) ; // Присвоить фокус на новое окно.
    window . opener ; // свойство вернет 0, если это окно "родительское". И верент ссылку на окно если его открыли.
    w . blur ( ) ;
    w . print ( ) ;
    w . scrollTo ( 150 , 150 ) ;
    w . scrollBy ( 150 , 150 ) ;
    w . moveTo ( 150 , 150 ) ;
    w . moveBy ( 150 , 150 ) ;
    w . resizeTo ( 150 , 150 ) ;
    w . resizeBy ( 150 , 150 ) ;
    //
    //
    // Работа с фреймами.
    < iframe name = "first" src = "frame1.html" > < / iframe >
    window . frames
    frames . length ;
    frames [ 0 ]
    alert ( frames . first . test_frame ) ; // переменная test_frame объеявлена на странице фрейма(в скрипте)
    // из фрейма можно получить доступ к переменным родительского окна с помощью parent(родитель) либо top(самое первое окно)
    alert ( parent . var_name ) ;
    alert ( top . var_name ) ;
    //
    //
    // window.navigator
    navigator . userAgent ;
    navigator . platform ;
    //
    // window.screen
    screen . width ;
    screen . height ;
    //
    // window.location
    location . hash ;
    location . host ;
    location . hostname ;
    location . href ;
    location . pathname ;
    location . protocol ;
    location . search ;
    location . assign ( 'http://wwww.ya.ru' ) ;
    window . location = 'http://wwww.ya.ru' ;
    location . replace ( 'http://wwww.ya.ru' ) ;
    location . reload ( ) ;
    location . toString ;
    //
    // window.history
    history . length ;
    history . back ( ) ;
    history . forward ( ) ;
    history . go ( - 2 ) ;
    history . pushState ( ) ;
    //
    //
    // DOM
    // выборка элементов
    document . getElementById ( ) ;
    document . getElementsByClassName ( ) ;
    document . getElementsByTagName ( ) ;
    document . getElementsByName ( ) ;
    document . querySelector ( ) ;
    document . querySelectorAll ( ) ;
    //
    // поиск структурно-связанных узлов
    block . parentNode ;
    block . childNodes ;
    block . children . length ;
    block . nextSibling ;
    block . previousElementSibling ;
    block . firstChild ;
    block . lastElementChild ;
    block . childElementCount ;
    //
    // создание элементов
    document . createElement ( 'div' ) ;
    document . createTextNode ( 'text' ) ;
    var frag = document . createDocumentFragment ( ) ;
    // вставка элементов
    block . appendChild ( elem ) ;
    block . insertBefore ( elem , child_name ) ;
    block . insertAdjacentHTML ( 'beforebegin' , new_elem ) ;
    // удаление элементов
    block . removeChild ( block . firstElementChild ) ;
    // замена элементов
    block . replaceChild ( new_elem , old_elem ) ;
    // работа с аттрибутами
    block . getAttribute ( 'class' ) ;
    block . setAttribute ( 'src' , 'img.jpg' ) ;
    block . removeAttribute ( 'href' ) ;
    block . hasAttribute ( 'name' ) ;
    // работа с Node
    block . nodeValue ;
    block . nodeType ;
    block . nodeName ;
    // работа с формами
    document . forms . my_name . my_input . type ;
    document . forms . elements [ 0 ] . value ;
    my_form . my_radio [ 0 ] ;
    // innerHTML
    var my_html = block . innerHTML ;
    block . innerHTML = '

    Test

    ' ;

    // взаимодействие с css
    elem . style . fontSize = '24px' ;
    //
    //
    // События
    // window
    window . onload
    window . onbeforeunload
    window . onfocus
    window . onblur
    window . onresize
    window . onscroll
    // mouse
    onclick = function ( e )
    e . altKey , e . shiftKey , e . ctrlKey
    e . clientX , e . clientY
    e . button
    >
    onmousemove
    onmousedown
    onmouseup
    onmouseover
    onmouseout
    onmousewheel
    // keyboard
    obj . onpresskey = function ( e )
    e . keyCode
    >
    onkeydown
    onkeyup
    // forms
    obj . onchange
    obj . oninput
    obj . onfocus
    obj . onblur
    obj . onsubmit
    obj . onreset
    // метод addEventListener регистрирует обработчики событий
    addEventListener ( 'click' , myFunc , false ) ;
    /* Внедрение JS в HTML. Синтаксис */
    1. < script type = "text/javascript" >code . . . < / script>
    Если JS встроен в < head >то сначала отрабатывает скрипт , потом загружается html . Если скрипт встроен в < body >,
    то отработает html расположеный выше скрипта .
    2. внешний файл
    3. встраивание кода js через обработчики событий
    /*При клике по тексту заголовка отработает код, описанный внутри onclick="" */
    < h1 onclick = "alert('Вы кликнули мышью')" >Заголовок < / h1>
    4. Передача кода скрипта в url . Надо использовать псевдопротокол js . Этот специльный тип протокола означает , что
    тело url адреса представляет собой js код .
    < a href = "JavaScript:alert('Hello')" >ссылка < / a>
    - завершить работу функции return ;
    /* Переменные и типы данных */
    Переменная - определенный именованный участок в памяти .
    /* зарезервированные слова. Не называть переменные. */
    try var void with debugger default catch break do
    Для удобства сначала переменные объявляют , потом присваивают значения .
    /* NULL TYPE */
    хранит в себе одно значение null ( не строка , именно значение ) . Это отсутствие значения , пустота . Если переменной присваиваем
    null , переменная пустая , но она определена . Зачем нужно такое значение ? Если в функцию не пришел определенный набор
    значений , то значит расчет не возможжен . И как результат работы функции можно вернуть null . Потом проверяем есть
    ли значение в результате функции .
    typeof ( name ) ; функция возвращает тип данных .
    /* UNDEFINED TYPE */
    Неопределенный тип данных . Содержит в себе только одно значение undefined . Говорит о том что значение переменной
    вообще отсутствует . Можем получить undefined когда обратимся к только что определенной переменной , которой
    еще не присвоили значение . Обычно значение null мы присваиваем сами в каких - то своих целях , а undefined
    получаем в результате неправильных действий , ошибочных выводов на экран и т . д . Также undefined возвращается
    функциями , которые не имеют возвращаемого значения .
    /* NUMBER TYPE */
    В js нет целых и действительных , все вещественные .
    Числовой тип данных . Можем записывать числа как в 10 - ричной форме , так и в 16 - ричной и 8 - ю . Мы можем задавать
    значения , используюя 16 - ю , 8 - ю сист . исч . , но js при отображении на экран переведет в 10 - е значение .
    Функция Number ( var ) приводит к числовому типу данных .
    % - оператор отсаток от деления
    var a = 7 , b = 3 , c ;
    c = a % b ; /* 1 */
    - деление на 0 вернет infinity ( бесконечность ) , не ошибку .
    - 0 / 0 , infinity / infinity , корень квадратный из отрицательного числа вернет NaN ( not a number не число ) . Т . е . те операции
    которые провести невозможно .
    Функция isNaN проверяет что содержится в переменной "не число" или нет . Если NaN вернет true ;
    Функция isFinite ( myVar ) возвращает истину , если переменная является числом отличным от NaN , и отличным от infinity и - infinity .
    /* STRING TYPE */
    Строка - упорядоченная последовательность значений . Строка - неизменный тип данных .
    - Если мы хотим вывести в строке двойную кавычку - используем обратный слэш \ . Экранирование кавычек .
    Если ставим \ , то следующий за ним символ уже не воспринимается интерпритатором js как управляющая конструкция .
    Ковычка становиться частью обычного текста .
    var str = "стро\"ка" ;
    - перенос строки \ n . var str = "стро\nка"
    - табуляция \ t .
    - конкатенация str1 + " " + str2
    Строки являются последовательностями 16 - и битных челочисленных значений и сравнение строк сводится к числовому сравнению
    этих же значений .
    var str1 = "new" ;
    var str2 = "new 2" ; // str1 меньше str2
    if ( str1 > str2 )
    document . write ( "str1 больше str2" ) ;
    >
    else
    document . write ( "str1 меньше str2" ) ;
    >
    Такое сравнение строк дает порой неожиданные результаты , поэтому для сравнения строк используется другой метод .
    /* метод write. выведет строку на экран. Если скрипт прописан в head, то данные выводятся сразу после открывающего
    тега , т.е. в начале */
    document . write ( "hello" ) ;
    /* BOOLEAN TYPE */
    функцияя Boolean ( var ) приводит переменную к логическому типу данных .
    var test = '10' + '20' ; /* вывод 1020 - строка */
    var test = '10' * '20' ; /* 200 число. Выполниться неявное преобразование типов */
    var test = 10 * '20' ; /* 200 число */
    var test = 'str' * "str2" ; /* NaN */
    var x = 10 ; var test = x + '' ; /* приведение к строке */
    var x = '10' ; var test = + x ; /* придение к числу */
    - x тоже приводит к числу , но меняет при этом знак на противоположный .
    0.2 можно записать как .2
    /* Условные операторы, сравнения, switch */
    == равенство ( не берет во внимание типы данныхоперандов ) '10' == 10 /* true */
    === оператор идентичности
    != без учета типа данных
    !== сравнивается с учетом типа даннх
    < >блок кода в фигурных скобках еще называют составным оператором
    else if ( ) < >/* раздельно */
    /* switch сравнивает и ищет совпадения по оператору идентичности, т.е. сравнивает типы данных.
    оператор switch используется только для чисел и строк */
    switch ( test )
    case null :
    alert ( "null" ) ;
    break ;
    case "string" :
    alert ( "string" ) ;
    break ;
    default:
    alert ( "default" ) ;
    >
    // как сделать так, чтобы определенный участок кода будет выполняться на каких-то одинаковых равных условиях.
    // т.е. alert("null") будем выводить, если test = null и test = ''.
    // Если нужно проверить несколько идентичных условий, но при этом код выполняется один.
    case ( null ) :
    case ( '' ) :
    alert ( "null" ) ;
    break ;
    // ДЗ
    alert ( 0.1 + 0.2 ) ; // 0.30000000004
    // появляется погрешность
    // все числа в js храняться в формате float 64, т.е. все числа представлены как вещественные и для их вывода
    // используется 64-х битный формат данных, т.е. это 8 байт с плавающей точкой
    // 5. Циклы
    // условие выхода из цикла - это то, что условие цикла в какой-то момент должно вернуть false.
    // вложенные циклы удобно использовать для создания таблиц. Во вложенном цикле переменная счетчика цикла
    // должна иметь другое название.
    //цикл while
    while ( i < 10 )
    document . write ( i + '
    ' ) ;
    i ++ ;
    >
    // цикл do while
    do
    if ( i == 5 )
    i ++ ;
    continue ;
    >
    document . write ( i + '
    ' ) ;
    >
    // инструкция continue - переход на следующую итерацию цикла
    // инструкция break завершает выполнение цикла
    // цикл for
    for ( инициализация ; проверка ( условие выхода из цикла ) ; обновление )
    // код цикла
    >
    for ( var i = 0 ; i < 5 ; i ++ )
    document . write ( i + '
    ' ) ;
    >
    // 6. Методы ввода-вывдоа.
    // данные методы являются методами глобального клиенского объекта js - объекта window.
    1. alert ( "test" ) ; // выводит модальное окно и ожидает пока пользователь его закроет
    2. var result = confirm ( "Подтвердите свой выбор" ) ; // предлагает кнопки ok и cancel, и возвращает логическое значение
    3. prompt ( "Введите ваше имя" ) ; // выводит сообщение на экран и ждет ввода произвольной строки от пользователя
    // и возвращает данную строку.
    // можно передавать второй параметр и он будет выведен как подсказка в поле ввода.
    prompt ( "Ваше имя" , "латинскими буквами" ) ;
    // Данные методы применяются довольно редко, т.к. модальное окно никак не форматируется. Используется для отладки
    // и сервисных сообщений.
    //
    //
    // пример. В переменную login сохраним значение отработки метода prompt. Т.е. предложим пользователю ввести логин.
    do
    var login = prompt ( "Ваш логин" ) ;
    // спросим правильно ли пользователь ввел логин
    var correct = confirm ( "Ваш логин:" + login + " \nПоддтвердите введенные данные." )
    >
    // условие выхода из цикла - когда пользователь подтвердит свой логин и в переменной correct будет лежать true
    while ( correct == false ) ; /* или */ while ( ! correct )
    alert ( "Ваш логин " + login ) ;
    //
    // метод также выводит модальное окно, но его содержание мы можем выбирать по своему усмотрению.
    // первым параметром принимает путь той страницы, которая откроется в новом модальном окне
    // второй параметр это текст, который будет отбражаться на странице
    // третий это параметры самого модального окна - ширина и высота
    showModalDialog ( "http://localhost/form.html" ,
    "" ,
    "dialogheight : 200px , dialogwidth : 300px" ) ;
    // содержание страницы
    // доступ к введенному тексту мы сможем получить в скрипте
    Введите текст < br / >
    < input type = "text" / > < br / >
    Введите текст < br / >
    < input type = "text" / > < br / >
    Введите текст < br / >
    < input type = "text" / > < br / >
    < input type = "submit" / >
    < input type = "reset" onClick = "window.close()" / >// метод close() объекта window - закрытие текущего окна.
    < / form >
    //
    //
    // метод eval позволяет разбирать строковые выражения
    eval ( "2+3" ) ; // вернет 5
    eval ( "alert(2+3)" ) ; // выведет окно 50. т.е. обработался и alert и выражение внутри него.
    // ключевой особенностью данного метода является то, что данный метод использует окружение того програмного кода,
    // который и вызывает данный метод. Т.е. метод eval будет выполнять поиск значений переменных и определять
    // новые переменные функций. Этот метод сильно ухудшает читаемость кода, просто знать, если встретить в чужем коде.
    //
    //
    // инструкция void. Указывается перед своим единственным операндом любого типа.
    void 2 ;
    alert ( void 2 ) ; // вернет undefined потому что void вычисляет значение своего операнда, затем отбрасывает это значение
    // и возвращает undefined.
    // Применяется в адресах url.
    // При переходе по ссылке откроется новое пустое окно, а текущее окно полностью потеряет свой контент (надпись
    // [object Window]. Потому что конструкция window.open вернула нам некий объект и js сообщает, что вернулся
    // определенный объект, но нам нужно было просто открыть новое окно, поэтому это возвращаемое значение
    // нам нужно было бы отбросить, для этого используется void
    < a href = "JavaScript: void window.open()" >Ссылка < / a >
    // 7. Массивы
    // Массив - упорядоченный набор значений.
    // массив может содержать пустые ячейки, в них храниться значение undefined. Такие массивы называются разряженными.
    var arr = [ 5 , 7 , , 9 ] ;
    var arr2 = [ , , ] ; // этот массив не имеет элементов, но его длина равна 2. Последняя запятая необязательна и
    // не учитывается, т.е. [5,7,9,];
    var arr3 = new Array ( ) ; // используя такую запись мы вызываем метод конструктора объекта Array.
    //
    document . write ( arr ) ; // на экране увидим массив в виде строки. Потому что массивы ведут себя как объекты и
    // практически у каждого объекта есть метод toString. Данный метод автоматически отрабатывает,
    // когда мы пытаемся вывести на экран какое-то значение. toString преобразовывает массив
    // в строку через запятые.
    //
    arr . length ; // свойство длина массива
    //
    // можно ограничить длину массива. Если длина меньше, то лишняя часть будет отброшена. Если задается длина
    // большая, то будут созданы пустые ячейки.
    var arr = [ 2 , 3 , 4 , 5 , 6 , 7 , 7 , 7 ] ;
    arr . length = 4 ;
    alert ( arr ) ; // 2,3,4,5
    //
    var arr = [ 1 , 3 , 5 ] ;
    arr [ 100 ] = 0 ;
    document . write ( arr . length ) ; // 101
    //
    arr [ "20" ] = 0 ; // js ожидает числовой тип данных, если сможет успешно перевести, то создаст ячейку под номером 20.
    //
    //
    // цикл for in применяется для обхода либо объектов либо массивов
    for ( /*переменная для индексов*/ in /*массив для прохода*/ )
    // код цикла
    >
    //
    // объявляем пустую переменную index и в нее на каждой итерации цикла будет поподать индекс массива array.
    for ( var index in array )
    alert ( array [ index ] ) ;
    >
    //
    //
    // многомерный массив
    // js не поддерживает многомерные массивы. .
    var arr = [ 1 , 2 , 3 , [ "hello" , "world" ] ] ;
    alert ( arr [ 3 ] [ 1 ] ) ; // world
    //
    //
    // методы массивов
    var arr = [ "мандарин" , "апельсин" , "груша" , "банан" ] ;
    join ( ) ; // преобразует элементы массива в строку
    // если мы передадим методу join параметр, то он будет использоваться как разделитель вместо дефолтной запятой
    arr . join ( " |---| " ) ;
    //
    reverse ( ) ; // возвращает массив в обратном порядке. Данный метод не создает новый массив, он выполняет изменения
    // существующего массива.
    //
    sort ( ) ; // сортирует элементы в исходном массиве. Сортирует массив так, как будто элементы массива это строки.
    // В алфавитном порядке.
    // сортировка цифр 1,100,11,111,2,200,22,222,3,4,5
    // чтобы отсортировать массив как обычные числа методу sort нужно передать функцию, которая будет описывать
    // правила сортировки. В методе sort именовать функцию не нужно - мы используем анонимную функцию.
    // передадим функции 2 параметра. a и b это какбы ячейки массива. Правила сортировки описываем для двух
    // произвольных значений. Данная функция должна возвращать 3 определенных значения. Если будет возвращено -1(любое < 0),
    // значит элемент a должен следовать до элемента b. Если вернется 1 (любое число больше 0), значит первый элемент a должен
    // идти после элемента b. Если вернем return 0; то порядок следования элементов a и b как бы не важен, другими словами a==b.
    array . sort ( function ( a , b )
    if ( a < b )
    if ( a > b )
    return 0 ;
    > ) ;
    //
    //
    // метод concat() позволяет создавать и возвращать новый массив, который содержит элементы исходного массива и те элементы,
    // которые переданы параметром методу concat(). Данный метод используется редко, т.к. массивы можно создать напрямую
    // обращаясь к его элементами.
    var arr = [ "a" , "b" , "c" ] ;
    // мы хотим создать новый массив.
    var a = arr . concat ( "d" , "e" , "f" ) ;
    document . write ( a ) ; // a,b,c,d,e,f
    //
    //
    // метод slice возвращает подмассив, либо фрагмент исходного массива. Принимает 2 параметра - начало и конец того
    // подмассива, который мы хотим получить. slice не изменяет исходный массив.
    var arr = [ "a" , "b" , "c" , "d" , "e" , "f" ] ;
    // чтобы получить элементы "c" и "d". Указываем начальный индекс 2. А конечный указваем на 1 больше, т.е.
    // он не будет включен в подмассив.
    arr . slice ( 2 , 4 ) ; // "c","d"
    // если указать 1 параметр, то получим подмассив от этого индекса до конца массива.
    arr . slice ( 2 ) ; // "c","d", "e", "f"
    // отрицательный параметр вернет элементы с конца массива. Причем -1 это индекс последней ячейки (не 0).
    arr . slice ( - 2 ) ; // "e", "f"
    //
    //
    // метод splice позволяет выполнять вставку и удаление неких элементов из массива. Данный метод изменяет исходный массив.
    // первый аргумент метода splice показывает позицию в массиве, начиная с которой будет выполняться вставка или
    // удаление данных. Второй параметр показывает количество элементов, которые необходимо вырезать.
    var arr = [ "a" , "b" , "c" , "d" , "e" , "f" ] ;
    arr . splice ( 2 , 2 ) ; // a,b,e,f
    // если второй параметр не задать, то удаляться все элементы из данного массива до конца строки.
    arr . splice ( 2 ) ; // a,b
    // метод splice возвращает вырезаные элементы, т.е.
    alert ( arr . splice ( 2 , 3 ) ) ; // c,d,e
    // после второго параметра можно элементы, которые будут добавлены в исходный массив начиная с позиции, указанной
    // в исходном элементе.
    arr . splice ( 2 , 3 , "hello" , "world" ) ;
    // чтобы не удалять никаких данных, вторым параметром передадим 0
    arr . splice ( 2 , 0 , 12 , 15 ) ;
    //
    //
    // методы для работы с последней ячейкой массива. Эти методы изменяют исходный массив.
    push ( ) ; // добавляет элементы в конец массива и возвращает длину измененного массива.
    var arr = [ 1 , 2 ] ;
    arr . push ( 3 ) ; // 1,2,3
    //
    pop ( ) ; // удаляет и возвращает последнюю ячейку массива.
    //
    //
    // методы для работы с началом массива. Изменяют исходный массив.
    var arr = [ 1 , 2 ] ;
    // unshift() добавит новый элемент в начало массива. Возвращает длину нового массива.
    arr . unshift ( 0 ) ; // 0,1,2
    // shift() удаляет первый элемент массива. Возвращает удаленный элемент.
    var arr = [ 1 , 2 ] ;
    arr . shift ( ) ; // вернет 1. arr = [2].
    //
    //
    // оператор delete удаляет ячейку массива. Значение будет удалено, но ячейка останестся со значением undefined.
    delete arr [ 1 ] ;
    // эта запись равносильна
    arr [ 1 ] = undefined ;
    // т.е. в отдичие от метода shift, инструкция delete не изменяет длину исходного массива.
    //
    //
    // инструкция in применяется чтобы проверить существует ли какое-то свойство в объекте, либо элемент в массиве
    // существует ли в массиве arr эдемент с индексом 1
    if ( 1 in arr )
    alert ( arr [ 1 ] ) ;
    >
    else
    alert ( "not" ) ;
    >
    //
    //
    // Как проверить что в переменной содержиться массив. Параметром передается переменная, которую мы проверяем.
    Array . isArray ( arr ) ;
    //
    // создать двумерный массив, в котором содержиться таблица умножения. Чтобы вывести умножение пар чисел необходимо
    // arr[5][5] в певрой ячейке 1 множитель во второй яч 2 множ. Данное выраж должно вернуть 25.
    // 8. Работа со строками.
    // у строки есть одно свойство length.
    str . length ;
    // способ создания строки. Образаемся к объекту String.
    var str = new String ( "hello world 112 world " ) ;
    //
    // методы для работы со строками.
    str . charAt ( 5 ) ; // str[5]; Не меняет исходную строку. Принимает индекс. Возвращает элемент строки под этим индексом.
    str . concat ( "new string" ) ; // Данный метод выполняет аналагичную операцию оператора +, т.е. конкатенация строк. К исходной
    // строке добавляет новую строку
    str . indexOf ( "world" ) ; // производит поиск подстроки в исходной строке. Возвращает индекс с которого подстрока
    // входит в исходную строку. Ищет индекс первого вхождения такой подстроки.
    str . lastIndexOf ( "world" ) ; // поиск последнего вхождения подстроки в строку
    str . split ( "," ) ; // разбивает строк и возвращает массив. Разбивает по разделителю, который передаем параметром.
    // Если не передавать разделитель в массив попадет вся строка. В виде разделителя может быть
    // шаблон регулярного выражения.
    str . replace ( "world" , "new string" ) // выполняет замену первого вхождения подстроки в исходную строку.
    // 1 параметр = та подстрока, которую мы хотим заменить. 2 параметр - строка на которую происходит замена.
    str . substr ( 7 , 5 ) ; // возвращщает подстроку, которая начинается с индекса, переданного первым параметром. Длниа
    // передается 2 параметром. Не рекомендуется передавать отриательный параметр, т.к. IE может заменить его 0.
    str . substring ( 2 , 5 ) ; // возвращает подстроку от 1 параметра, до позиции указанной во 2 параметре, но последний символ
    // не включается в возвращаемую строку. Если передать отрицательное число, оно будет заменено 0.
    // Если второй параметр меньше первого, то они меняются местами.
    str . toUpperCase ( ) ;
    str . toLowerCase ( ) ;
    str . toLocaleUpperCase ( ) ; // возвращает новую строку, в которой все буквы исходной строки заменены на большие, но с учетом
    str . toLocaleLowerCase ( ) ; // национальных установок операионной системы. Кодировок языка очень много и если кодировка
    // языка как-то противречит правилам юникода, то лучше использовать тот метод. Применяется редко.
    str . slice ( 6 , 10 ) ; // возвращает подстроку с индекса, переданного первым параметром, и до индекса переданного 2 параметром.
    // последний символ не включается. Можно использовать отрицательный аргумент.
    str1 . localeCompare ( b ) ; // стравнение строк с учетом национальных особеннойстей. -1 если str1 < str2. 0 равны. 1 str1>str2.
    //
    //
    // методы для работы с регулярными выражениями
    str . search ( / [ 0-9 ] / ) ; // выполняет поиск в исходной строке по шаблону регулярного выражения переданного параметром.
    //Возвращает позицию первого найденного совпадения. Если совпадений не найдено, возвращается -1.
    str . match ( / [ 0-9 ] + / ) ; // выполняет поиск регулярного выражения в исходной строке. Возвращает массив найденныых подстрок
    // или 0 если совпалений нет.
    //
    //
    // устаревшие методы
    str . bold ( ) ; // оборачивает строку в тег .
    str . blink ( ) ; // мигающая строка
    str . fixed ( ) ; //
    str . fontcolor ( "red" ) ;
    str . fontsize ( 20 ) ;
    str . italics ( ) ; //
    str . link ( "http://google.com" ) ; //
    //
    // вывести подальное окно и предложить пользователю ввести строку. Чтобы эта строка содержала в себе некие слова,
    // разделенные |. Затем надо разбить строку на массив и вывести каждое слово на новой строке. Если пользователь нажмет
    // отмена, надо заново отобразить это модальное окно. Нельзя передать пусую строку. ВВеденная строка обязательно
    // должна содержать разделители. Если в конце строки разделитель, чтобы не полуилась лишняя пустая ячейка.
    //
    // вывести строку в которой символы следуют наоборот
    // 9. Функции
    // Т.к. js объектно-ориентированный язык, то функции в js являются объектами.
    // объявление функции через оператор function. Присваиваем функции имя. Можем вызвать функцию на исполнение до ее объявления.
    function func ( a , b )
    //
    // присваиваем функцию переменной. НЕЛЬЗЯ вызвать функцию на исполнение до ее присваивания переменной. Имя функции не задаем.
    // Присваиваем имя функции только в том случае, если необходимо использовать имя функции в самой же функции.
    // (рекурсивная функция).
    var func = function ( a , b ) < . >;
    func ( 1 , 2 ) ;
    // такую функцию сразу можно вызвать на исполнение, передав параметры в скобках. Не использовать ухудшает читабельность кода.
    // Это как бы однократная функция, т.е. дальнийшие ее вызовы в коде не будут работать.
    var func = ( function ( a , b ) < . >( 10 , 5 ) ) ;
    //
    //
    // рекурсивная функция
    function getStr ( )
    var str = prompt ( "Введите строку" ) ;
    // если пользователь закрыл модальное окно и в переменную str вернулся null - повторно вызываем функцию.
    if ( ! str )
    getStr ( ) ;
    >
    else
    alert ( str ) ;
    // используется для завершения работы функции
    return ;
    >
    >
    //
    // функции, у которых нет инструкции return, возвращают значение undefined.
    //
    // Интерпритатор js не проверяет типы данных параметров, переданных в функции.
    // в начале функций не забывать проводить проверки параметров на типы данных и т.д. Чтобы защитить
    // себя от ошибочных результатов отработки функции.
    function func ( str )
    document . write ( "

    " + str + "

    " ) ;

    >
    func ( "string" ) ;
    // если функции не переданы параметры, которые она ожидает, то этим параметрам присваивается значение undefined.
    // Параметры, которые мы передаем в функцию записываются в массив arguments. Мы можем не указывать в функции какие
    // аргументы она ожидает. Доступ ко всем переданным параметрам можно получить через массив arguments. Мы можем
    // манипулировать ячейками этого массива, дописывать в них, удалять и т.д.
    function func ( )
    document . write ( "

    " + arguments [ 0 ] + "

    " ) ;

    >
    func ( "string" ) ;
    //
    // Более того, мы можем создать функцию, которая будет выполнять прием любого неограниченного числа параметров.
    function max ( )
    var arr = arguments ; // необязательно
    for ( var i = 0 ; i < arк . lenth ; i ++ )
    .
    >
    >
    max ( 1 , 2 , 3 , 4 , 5 ) ;
    //
    // если в функции описаны 2 параметра, а ей переданы 3. Лишние параметры интерпритатор не учитывает, они отбрасываются.
    //
    // Если вы пишите отдельный модуль какого-то проекта, то чтобы не дублировать переменные обычно создают функцию,
    // выполняют какой-то код и потом просто эту функцию вызывают на исполнение. И переменные которые были созданы внутри
    // функции являются локальными и самом скрипте, как глобальные переменные они не будут доступны и конфликта не будет.
    function block ( )
    // code
    >
    block ( ) ;
    // если надо исключить даже имена функций можно создать анонимную функцию
    ( function ( )
    // code
    // потом сразу вызывается функция на исполнение - передаются параметры в скобках
    > ( a , b . . . ) )
    //
    //
    // функции могут быть вложенными. Вложенная функция имеет полный доступ к локальным переменным функции верхнего уровня.
    function myFunc ( x , y )
    alert ( x + y ) ;
    function myFunc2 ( )
    document . write ( x - y ) ;
    return ( x - y ) ;
    >
    return myFunc2 ;
    >
    myFunc ( 1 , 2 ) ;
    // функцию можно передавать параметром
    //
    // функции можно выносить в отдельный файл
    // Время и дата
    // В js существует объект Date(), содержащий все необходимые методы для работы с датаой и временем. Данный объект
    // на момент своего вызова хранит в себе как бы текущую метку времени.
    // Чтобы создать объект необходимо, с помощью ключевого слова new вызвать функцию конструктор данного объекта
    var now = new Date ( ) ;
    document . write ( now ) ; // отработает метод toString(), который преобрахует содержимое объекта в строку.
    now . toLocaleString ( ) ; // метод toLocaleString выводит дату и время в соответствии с региональными настройками компьютера польз
    now . toLocaleDateString ( ) ; // вывод даты, время отброшено
    now . toLocaleTimeString ( ) ; // вывод времени
    //
    // объект Date() хранит время момента своего создания, т.е. время в нем не изменяется динамически.
    //
    // Можно не только выводить но и задавать время и дату. Например нужно сделать таймер отсчитывающий время от начала акции.
    // Чтобы вывести до конца акции осталось 10 дней к примеру. Для этих целей необходимо работать с будущим временем, а не
    // с текущим. Для этих целей применяются методы задающие время.
    now . setFullYear ( 1990 ) ;
    now . setMonth ( 9 ) ;
    now . setDate ( 25 ) ;
    // можем изменять число месяца date, но не можем задать день недели, т.к. он расчитывается.
    now . setHours ( 13 ) ; // если интерпритатор видит, что мы задали большее количество часов, чем в сутках, он увеличит дату
    // и добавит к ней.
    now . setMinutes ( 59 ) ;
    now . setMilliseconds ( 100 ) ;
    now . setTime ( 100 ) ; // прошло 100 миллисекунд с 1970г.
    //
    //
    // Также объекту Date можно передавать параметры.
    // Задача. Отобразить сколько дней осталось до нового года.
    // Необходимо создать объект Date с датой нового года.
    var newYear = new Date ( 2016 , 0 , 1 ) ;
    // текущее время
    var now = new Date ( ) ;
    // можно использовать метод getTime(), либо обычное вычитание.
    var number_days = newYear - now ; // разность в количествах миллисекунд.
    // Т.к. дата установлена в миллисекундах, переведем в начале в секунды - поделим на 1000. Переведем в минуты - поделим на 60.
    // В часы - еще на 60. В дни - на 24.
    // Отбросим остаток с помощью parseInt
    alert ( parseInt ( number_days / ( 1000 * 60 * 60 * 24 ) ) ) ;
    //
    //
    // Метод parse() - статический метод объекта Date(), вызывается непосредственно у объекта Date(). Принимает один
    // строковый параметр, саму дату в виде строки, анализирует ее и возвращает количество миллисекунд с 1970.
    Date . parse ( ) ;
    // вывести количество дней и часо до 1 сентября 2016.
    // создать часы в браузере(рекурсия, setTimeout. document.write не подойдет.)
    // 11. Математические операции объект Math. Объект Number.
    // Объект Math содержит константы и методы для выполнения математических операций. Объект Math не имеет конструктора.
    // Т.е. мы не можем создать новый объект с помощью ключевого слова new Math(). Получить доступ к методам можно с
    // помощью оператора точка Math.
    var test = - 10 ;
    Math . abs ( test ) ; // число по модулю 10
    Math . round ( x ) ; // округлить число до ближайшего целого в соответсвии с математическими правилами.
    Math . ceil ( x ) ; // округлить число вверх в независимости от того какая десятичная часть. 45.1 -> 46.
    Math . floor ( x ) ; // округляет число до ближайшего меньшег
    Math . max ( 10 , 23 , 45 , - 1 ) ; // вычисляет максимально число из переданных
    Math . min ( 1 , 2 , 3 ) ; // вычисляет минимальное число из переданных
    Math . pow ( x , y ) ; // вычисляет степень числа. 1 параметр - число. 2 пар - степень.
    Math . sqrt ( x ) ; // квадратый корень
    Math . random ( ) ; // возвращает случайно сгенерированное число от 0 до 1
    Math . acos ( - 1 ) ; // арккосинус. Принимает от -1 до 1
    Math . asin ( 1 ) ; // арксинус. от -1 до 1
    Math . atan ( ) ; // арктангенс
    Math . atan2 ( y , x ) ; // арктангенс параметров y и x. Это координаты.
    Math . cos ( x ) ; // косинус. x - значение угла в радианах. Чтобы перевести градусы в радианы - умножить на 0.17.
    Math . PI ; // число Пи константа
    Math . E ; // константа екпонента
    Math . exp ( x ) ; // вычисляет экспоненту принимает степень
    Math . LN10 ; // константа натуральный логорифм числа 10.
    Math . LN2 ; // константа натуральный логорифм числа 2.
    Math . log ( x ) ; // вычисляет натуральный логорифм любого числа больше 0.
    Math . LOG10E ; // логориф по основанию 10 константы е
    Math . sin ( x ) ; // позволяет определить синус угла. x - угол в радианах.
    Math . tan ( x ) ; // x - угол в радианах. тангенс
    //
    //
    // Объект Number.
    var numb = 4 ; // эта запись равносильна
    var numb = new Number ( 4 ) ; // если это объект то у него есть методы и свойства
    //
    Number . MAX_VALUE ; // константа максимальное значение, которое можно присвоить переменной
    Number . MIN_VALUE ; // константа
    Number . NEGATIVE_INFINITY ; // - бесконечность
    Number . POSITIVE_INFINITY ; // + бесконечность
    //
    Number ( x ) ; // преобразует переданный параметр в числовой тип данных (дробное)
    numb . toString ( ) ; // преобразует число в строку
    numb . toFixed ( 2 ) ; // преобразует число в строку. Принимает число цифр после точки
    nump . toPrecision ( numb ) ; // форматирует значащие цифры числа.
    //
    // реализовать возможность генерации случайного числа от 0 до 100. целые числа.
    // выведите на экран тангенсы Пи, Пи/2, /3
    // Объекты.
    // И рег.выр. и массивы и функции являются объектами.
    // Объект это контейнер из ключей и свойств.
    // 2 способа создания объекта.
    var obj = new Object < >; // не использовать, литерал короче и удобней
    var obj = < >; // литерал объекта
    //
    // Свойство объекта это переменная объявленная внутри объекта.
    // именем свойства - ключом может быть любая строка, в том числе пустая. Обычно пишется без ковычек.
    // значение свойства может быть любым - другим объектом, функцией, числом, булевым значением, кроме undefined.
    // Разделяется имя и значение двоеточием. Свойства разделяются запятой.
    var obj =
    str_name : 'str_value' ,
    func : function ( )
    > ;
    console . log ( obj . str_name ) ; // str_value
    //
    // Объекты очень уобны для хранения и организации данных. И т.е. в объекты можно вкладывать другие объекты, то можно
    // делать полезные древовидные структуры.
    // Чтобы достать свойсто можно использовать 2 нотации - точечную и квадратные скобки.
    // Когда надо доставать разные свойства используем переменную и достает эти свойства с помощью квадратных скобок.
    // А в любом другом случае используется точечная нотация.
    var prop = 'str_name' ;
    var prop = 'func' ;
    obj [ prop ] ;
    // При попытке обратиться к несуществующему свойству получим undefined.
    // Чтобы задать свойство по умолчанию можно использовать оператор "или". Т.е. если у нас нет этого свойства, оно пустое
    // то можно его сразу задать. Т.е. если слева false, то берется справа.
    console . log ( obj . fff_name || 'fff_value' ) ;
    //
    // Присвоение. Добавить новое свойство или изменить старое.
    obj . ddd = 'Gag 9' ;
    //
    // Объекты всегда передаются по ссылкам, они никогда не копируются.
    var a = < prop : 1 >, b = < prop : 2 >, c = < prop : 3 >;
    console . log ( a , b , c ) ; // Object Object Object
    // Но если объекты приравнять друг к другу, то все они имеют ссылку на один и тот же объект.
    a = b = c = < prop : 'allTheSame' >;
    console . log ( a , b , c ) ; // Object * 3
    //
    // У нас есть объект. Объявляем переменную y и присваиваем ей объект.
    var y = obj ;
    console . log ( y . str_name ) ; // str_value
    //
    // Удаление свойств. delete удаляет только свойство именно этого объекта, в свойства прототипа он не лезет.
    delete obj . func ;
    //
    // Доступ к объекту. Когда функция находиться в объекте, является его свойством, то такая функция называется методам.
    // Часто бывает нужен внутри метода доступ к самому объекту или к какому-то из его свойств. Используем ключевое
    // слово this.
    var obj =
    str_name : 'str_value' ,
    func : function ( )
    console . log ( this . str_name ) ;
    >
    > ;
    //
    // В js все переменные являются глобальными. Когда работаете в команде создается одна глобальная функция и в ней описывается
    // все приложение. Констант как таковых в js нет, обычно пишутся переменные заглавными буквами. Создается объект
    // MYAPP и внутри него перечисляются все свойства и методы, которые будут использоваться в приложение.
    var MYAPP = < >;
    //
    //
    // Каждый объект в js имеет второй объект, который асоциируется с ним называется прототипом. И первый объект наследует
    // от прототипа все его свойства. Все объекты созданные с помощью литерала объекта имеют один прототип
    var object = < >; // прототип Object.prototype
    var newDate = new Date ( ) ; // прототип Date.prototipe
    // Object.prototype не имеет прототипа и не наследует ничьи свойства. В свою очерендь Date.prototype наследует
    // Object.prototype. Т.е. Object.prototype это какбы основной прототип для всех объектов, которые наследуют его свойства.
    // Если мы вызовем у созданного объекта метод toString то он отработает, хотя мы его не определяли и ошибок при этом нет.
    // Потому что метод toString является составным методом Object.prototype и наш объект является наследником данного
    // объекта и получает доступ к этому методу.
    //
    // Реализуем функционал чтобы obj2 получал доступ к свойствам obj1. Есть метод create(), который создает новый объект и
    // использует свой первый параметр в качестве прототипа этого объекта. create это даже не метод, а статическая функция.
    var obj1 = < x : 1 >;
    var obj2 = Object . create ( obj1 ) ; // используя такую запись мы создали прототип для obj2. Теперь obj2 унаследовал все свойства
    // obj1. Как только вы создаете одноименное свойство с наследованным вы его переписываете
    // в obj2. Если изменить значение свойства в родителе, то изменения произойдут и в дочерних.
    //
    //
    var obj =
    x1 : 100 , x2 : 200 , x3 : 300
    >
    for ( var i = 1 ; i < 4 ; i ++ )
    console . log ( obj [ 'x' + i ] ) ;
    >
    //
    //
    // Проверить наличие свойств у объекта.
    obj . hasOwnProperty ( "property" ) ; // true or false. Но если свойство наследуется то этот метод вернет false.
    alert ( "property" in obj ) ; // оператор in вернет true, если указанное свойство существует в объекте. Не важно наслед или нет
    alert ( obj . propetyIsEnumerable ( ) ) ; // Если свойство наследуется то этот метод вернет false.
    //
    //
    // Методы чтения и записи свойств. Это специальные методы, которые определяются не при помощи ключевого слова function,
    // а при помощи ключ. слов get и set. get определяет код функции, когда будем обращаться к какому-то свойству.
    // Метод set определяет код функции, когда мы пытаемся свойство изменить.
    var obj =
    x : 100 ,
    y : 20 ,
    get test ( )
    return this . x + this . y ;
    >
    >
    console . log ( obj . test ) ;
    // если попытаемся изменить метод test, то изменений не будет, т.к. мы определили для данной переменной метод get, который
    // отрабатывает во время обращения к данной функции.
    obj . test = 1000 ;
    //
    //
    // Определить свой метод.
    var obj =
    myMethod : function ( )
    // code
    >
    >
    // ывет|тип кузова Создать объект k. Свойство color, type, data
    // Объект window.
    // Фрейм это другая страница на html странице.
    < iframe name = 'ya' src = 'frame.html' > < / iframe >
    //
    //
    // Таймеры
    setTimeout('func()', 2000); // Выполняет действие с задержкой. Возвращает некий идентификатор, для того, чтобы его передать
    // в clearTimeout(применяется редко т.к. обычно действие выполняется однократно. Чаще
    // применяется для setInterval)
    function time()
    setTimeout ( "alert('hello this is set timeout'), 2000" ) ;
    >
    < h1 OnClick = "time()" >Заголовок < / h1 >
    //
    setInterval('func()', 1000); // позволяет многократно вызывать опреденный код или функцию.
    var interval;
    function intervar()
    interval = setInterval ( my , 2000 )
    >
    var n = 1; // просто счетчик
    function my()
    ++ n ;
    console . log ( n ) ;
    if ( n == 4 )
    clearINterval ( interval ) ;
    >
    >
    //
    //
    // window может управлять окнами - открывать, закрывать.
    var w = window . open ( " http : //ya.ru", "mywindow", "width:400,height:350,menubar=1, toolbar=1, resizable=0, scrollbars=1");
    // открывает окно(вкладку). Пустое если без параметров.
    // Метод open возвращает ссылку на открытое окно(переменная w). Это даже не ссылка, это объект window
    // для нашего нового окна. Это нужно чтобы закрыть данное окно.
    // 1 параметр - путь html страницы, которая будет открыта в новом окне
    // 2 параметр - имя окна. Параметр name служит также целью(т.е. в каком окне будет открыто новое окно).
    window . open ( " http : //google.com", "mywindow"); // Гугл будет открыт в этом же окне mywindow.
    // 3 - параметры позволяющие задать ширину/высоту окна/наличие в новом окне панели инструментов/адресной стр.
    // 3 параметр это обычная строка в которой через запятую перечислены соответствующие настройки и иъ значения.
    // width, height - ширина, высота окна
    // menubar - панель меню(1 есть, 0 нет)
    // toolbar - тулбар
    // resizable - возможность изменять окно в размерах. В мозиле не робит, всегда включена.
    // scrollbars - полоса прокрутки
    //
    //
    w . close ( ) ; // метод close() закрывает указанное(w) окно.
    var w ;
    function op ( )
    w = window . open ( " http : //ya.ru", "mywindow");
    >
    function cl ( )
    w . close ( ) ;
    >
    < h2 OnClick = " op ( ) " >Открыть окно < / h2 >
    < h2 OnClick = "cl()" >Закрыть окно < / h2 >
    //
    //
    // Взаимодействие с новым открытым окном.
    window.opener; // свойство вернет 0, если это окно "родительское". И верент ссылку на окно если его открыли.
    // index.html
    function new_window()
    w = window . open ( "new_html.html" ) ;
    >
    var glob_var = "test string";
    function get_str() < // вывод "test string" 100
    console . log ( get_str ( ) ) ;
    w . remake_str ( ) ;
    console . log ( get_str ( ) ) ;
    >
    // new_html.html
    function remake_str()
    opener . glob_str = 100 ;
    >
    //
    //
    w.focus(); // Присвоить фокус на новое окно.
    w.blur(); // снимает фокус с окна
    w.print(); // запускает комбинацию клавиш CTRL + P
    window.scrollTo(0, 100); // выполнить перемещение используя полосы прокрутки до указанных.
    window.scrollBy(0, 100); // выполнить перемещение используя полосы прокрутки на указанные пиксели.
    w.moveTo(300,300); // перемещает данное окно в указанную позицию. Задает абсолютную позицию.
    w.moveBy(50,50); // сдвигать на указанное количество пикселей.
    w.resizeTo(200,250); // изменяет размер окна до указанного
    w.resizeBy(20,20); // изменяет размер окна на заданные пиксели
    //
    //
    // Работа с фреймами.
    window.frames // это объект который содержиться внутри window
    frames.length; // вернет количество фреймов на странице
    //
    < iframe name = "first" src = "frame1.html" > < / iframe >
    // К фрейму можно обратиться по индексу
    frames[0]
    // либо по имени фрейма
    alert(frames.first.test_frame); // переменная test_frame объеявлена на странице фрейма(в скрипте)
    // из фрейма можно получить доступ к переменным родительского окна с помощью parent(родитель) либо top(самое первое окно)
    alert(parent.var_name);
    alert(top.var_name);
    // Объект window и BOM (объектная модель браузера).
    // Глобальный объект window состоит из 3 частей:
    // DOM объектная модель документа
    // BOM объектная модель браузера
    // и сам javascript все объекты, переменные, которые мы создаем записываются в объект window.
    var foo = 'String';
    console.log(foo); /* равносильна */ console.log(window.foo);
    // Все что мы выводим вне функций записывается в window.
    // console - объект внутри объекта window. log - его метод.
    //
    // Основные виды объектов, относящиеся к BOM.
    // 1. window.navigator это объект, в котором храниться вся информация о браузере и ОС.
    console.log(navigator);
    navigator.userAgent // вся информация о браузере
    navigator.platform // информация о ОС. Пригодиться для написания программ, где нужно проверять браузер и систему.
    // неактуальные свойства. С их помощью сложно определить браузер.
    navigator.appName // содержит имя браузера. Mozila, Chrome вернут Netscape. Opera-opera. Ie-Ie.
    navigator.appVersion // содержит номер версии сборки браузера
    navigator.javaEnabled // Вернет true, если браузер способен выполнять язык java.
    //
    // не очень актуальные методы
    navigator.cookieEnabled(); // проверить включены ли у пользователя cookie
    //
    // 2. Объект screen. В нем хранятся все данные о экране пользователя. Полезен для проверки если код выполняется на
    // маленьком разрешении на мобильниках.
    console.log(screen.width , screen.height ); // 1200 800
    //
    // 3. Объект location содержит информацию о текущем url.
    // Свойства
    location.hash; // вернет анкор, переданный в url. #top
    location.host; // вернет домен и порт(если есть в адресной строке) localhost:80
    location.hostname; // вернет только сам домен
    location.href; // хранит в себе полную адресную строку. Отрабатывает метод toString()
    location.pathname; // вернет путь от домена до GET параметров /page_1/article_1/index.html
    location.protocol; // вернет http:
    location.search; // хранятся GET параметры ?param=1&qwe=2. Самый полезное свойство.
    //
    // Методы
    location.assign("http://google.com"); // загружает и отображает адрес, который передается параметром данному методу.
    // Выполняет перенаправление
    window.location = "http://javascript.ru"; // перейти на другую страницу. С точки зрения правильности кода жедательно
    // использовать метод assign().
    location.reload(); // дает возможность перезагружать страницу с сервера. Будет циклически перезагружать стр.
    location.replace(); // аналогичен методу assign. В истории браузера новая ячейка не будет создана, будет переписана
    // существующая. Нельзя кликнуть назад.
    location.toString(); // возвращает полностью текущий url страницы. Отрабатывает автоматически при записи console.log(location)
    // Возвращает строковое представление url для объекта location.
    //
    //
    // 4. Коллекция frames содержит дочерние объекты(фреймы) которые используются на данной странице.
    //
    // 5. Объект history хранит в себе историю просмотра страниц. Позволяет переходить назад вперед по истории перехода страниц,
    // также позволяет без перезагрузки обновлять страницу браузера. На новых одностраничных ajax приложениях все это происходит
    // благодаря об. history. Объект history используется когда нужно организовать перемещение по внутренним страницам сайта
    // по истории.
    // Нет свойства или метода, который бы вернул пути посещенных страниц. Такое ограничение наложено с целью повышения
    // безопасности. Можем выполнять перемещение по элементам истории.
    // Свойство
    history.length; // количество элементов в списке истории.
    // Методы
    history.back(); // переход к предидущему элементу в истории посещений. Аналогичен нажатию кнопки назад в браузере.
    history.forward(); // вперед
    history.go(-2); // принимает параметром числовое значение и пропускает в истории заданное число страниц и выполняет
    // переход на необходимый элемент списка. Чтобы перейти назад передаем отрицательный элемент.
    // Чтобы перейти на 2 элемента назад.
    history.pushState('my_data', 'my title', 'index.html?q=2'); // Редкий метод. Добавляет новую запись в объект history,
    // т.е. в журнал посещений для данного окна, при этом
    // сохраняя структурированную копию данных, которые передаются ему 1 параметром, 2 параметр - title
    // название окна, 3 параметр - url той страницы, которая сохраняется в истории. url должен быть указан
    // относительно вашего текущего скрипта.
    history.replaceState(); // аналог предидущего. Вместо создания новой записи изменяет текущую запись. Браузеры могут
    // игнорировать этот метод. Редкий метод.
    // принят url, создать массив у которого ключи - названия GET параметров, значения - значения гет параметров
    //
    //
    //
    // Проблемы совместимости.
    // 1. Эволюционные проблемы
    // 2. Отсутсвие реализации
    // 3. Ошибки
    // Решение.
    // 1. Определить тип браузера. И уже под него разработать отдельный код.
    // 2. Подключение библиотек (js скриптов), которые будут обеспечивать совместимость со всеми браузерами.
    // 3. Использование фреймворков
    // 4. Проверка функциональных возможностей
    // 5. Условные комментарии html
    // 6. Условный комментарий js.
    // cc - condition compilation(условный комментарий)
    // @_jscript - переменная в IE всегда равна true.
    /*@cc_on
    @if(@_jscript)
    alert('this is IE');
    @else*/
    alert('another brower');
    /*@end
    @*/
    //
    //
    //
    // DOM. Объектная модель документа.
    // Скрипт подключать внизу страницы, иначе блоки к которым мы обращаемся еще не созданы.
    // Выбор элементов
    1. document.getElementById();
    < h2 OnCLick = "fucn()" >Выполнить функцию < / h2 >
    function func()
    var block = document . getElementById ( 'my_text' ) ;
    console . log ( block ) ; // Object HTMLParagraphElement
    >
    2. block = document.getElementsByName('my_name'); // выборка элементов по аттрибуту name(например у элементов формы).
    // name не уникальный элемент, может выбрать несколько (коллекию совпадений). Вернет Object NodeList. Ведет себя как
    // доступный только для чтения массив элементов.
    alert(block[0].innerHTML);
    //
    // Если на странице есть элементы с аттрибутами name, то у глобальго объекта window создаются свойства и именами этих
    // свойств. Тоже в объекте document. Т.е. чтобы о братиться к элементу с известным значением name='myName'.
    // Но document.getElementByName('myName') предпочтительней.
    var block = document.myName;
    //
    3. block = document.getElementsByTagName('p'); // выборка элементов по типу(имени тэга). Вернет Object HTMLCollection.
    // Формально это объект, но работаем с ним как с массивом. Если передать *, то будут выбраны все hTML тэги на странице.
    alert(block[0].innerHTML); // вывести HTML код первого выбранного параметра.
    //
    // Данный метод также доступен у объекта Element. Допустим выбрали див по id (это уже объект Element).
    // Но внутри него лежит < p >с текстом. Мы знаем что там параграф и нам нудно его отбросить,
    // чтобы получить только текст.
    var block = document.getElementById('myDiv');
    alert(block.getElementsByTagName('p')[0].innerHTML);
    //
    4. block = document.getElementsByClassName('my_class'); // выбор элементов по классам. Возвращается объект/массив.
    // Также вызывается не только у document, но и конкретно выбранного блока
    //
    5. querySelector('.my_class') // выборка элементов по селекторам css. Данный метод выполняет поиск по
    //указанному селектору. Вернет первое совпадение.
    var block = document.getElementById('my_id');
    alert(block.querySelector('#my_id').innerHTML);
    5.1. querySelectorAll('.my_class'); // вернет все элементы, с данным классом.
    querySelectorAll('#my_id')[0].innerHTML;
    //
    6. // Свойства отыскать структурно связанные элементы(родители, дочерние, братья)
    block.parentNode; // вернет родительский узел данного узла или null если нет родителя
    block.childNodes; // Вернет объект NodeList, который представляет все дочерние узлы
    block.firstChild; // первый дочерний элемент
    block.lastChild; // последний дочерний элемент
    block.previousSibling; // предидущий братский узел
    block.nextSibling; // сдежующий братский узел
    // nextSibling, previousSibling использовать не удобно, т.к. он постоянно возвразает пустой текстовый узел.
    block.previousElementSibling; // возвращается предидущий узел типа элемент, т.е. текстовый узел пропускается.
    block.nextElementSibling;
    // также с lastChild, firstChild. Пропускают текстовые узлы.
    block.lastElementChild;
    block.firstElementChild;
    block.nodeValue; // свойство хранит в себе значение текстового узла
    block.innerHTML; // HTML содержимое выбранного блока
    block.nodeType; // свойство вернет тип данного узла. Узлы типа document(родитель html) имют значение 9.
    // Все узлы типа Element имеют значение 1. Текстовый узлы - 3.
    block.nodeName; // вернет имя тэга элемента (P параграф)
    block.childElementCount; // количество дочерних элементов типа элемент
    block.children.length; // количество дочерних элементов
    //
    //
    //
    // Работа с аттрибутами. Чтобы получить значение какого-то стандартного аттрибута достаточно обратиться по его имени.
    img.src; // вернет значение аттрибута src для данного изображения.
    //
    // получим значение аттрибута method у текстовой формы
    var form = document.getElementsByTagName('form');
    console.log(form[0].method); // POST или GET
    //
    // Иногда имена аттрибутов совпадают с зарезервированными словами в js. Аттрибут class. Поэтому явно обратитьтся
    // к аттрибуту class нельзя block.class. Поэтому обращаемся к classNAme.
    block.className
    //
    1. img[0].getAttribute('class'); // метод позваоляет получить аттрибут по его стандартному названию
    2. img[0].setAttribute('src', 'img.jpg'); // установить значение аттрибута
    // установить значение аттрибута можно просто обратившись к его свойству
    img.src = "img.jpg";
    //
    // Редко используется
    // Спецификация html5 поддерживает создание пользовательских аттрибутов. Должен начинаться с "data-" потом имя аттр.
    < div data-my_attr = '#' >. < / div >
    // получить к нему доступ можно с помощью свойства dataset. Это объект пользовательских аттрибутов.
    dataset.my_attr
    //
    // Редко исп.
    img.attributes // объект, который содержит в себе все аттр. данного элемента. У объекта есть 2 свойства - name и value.
    // К конкретным аттр. можно добраться по индексам
    img.attributes[0].name; // width например
    img.attributes[0].value; // 150
    // К конкретным аттр. можно добраться по имени аттр.
    img.attributes['src'].value;
    //
    //
    // innerHTML
    var tag = document.getElementsByTagName('h2');
    tag[0].innerHTML = 'POSTS'; // изменить содержимое блока.
    //
    outerHTML; // хранит в себе код данного элемента вместе с тегами, которые образуют данные тег.
    // Когда мы присваиваем данному свойству значение, то содержимое замещает элемент целиком.
    //
    tag[2].insertAdjacentHTML('beforebegin',' < p >New < / p >'); // первый параметр - куда будет вставлена разметка, по отнощению
    // к выбранному элементу.
    // beforebegin - вставляет перед выбранным элементом
    // afterbegin - вставляет на место первого дочернего элемента
    // beforeend - вставляет на место последнего дочернего
    // afterend - после выбранного элемента
    //
    // вытаскивает только текст из определенных элементов. Отбрасывает теги.
    div.textContent;
    //
    div.hasAttribute('class'); // проверяет наличие аттрибута
    div.removeAttribute('class'); // удаляет аттрибут
    //
    //
    //
    // Создание узлов.
    var newNode = document.createTextNode('Содержимое текст узла'); // создает текстовый узел
    var newElem = document.createElement('div'); // создаем элемент, содержащий этот текстовый узел
    // Вставка узлов
    newElem.appendChild(newNode); // вызывается относительно узла родителя, становиться последним дочерним узлом.
    div.insertBefore(newElem, div_name); // 1 пар - вставляемый узел, 2 пар - узел, перед которым должен быть
    // вставлен новый узел. div_name - див полученный по id.
    // удаление элементов
    div.removeChild(div.firstElementChild); // вызывается не относительно узла, который должен быть удален, а
    // относительно рожителя удаляемого узла и принимает в качестве
    // параметра дочерний узел, который должен быть удален.
    // Или можно получить элемент, который нужно удалить, через него обратиться к родителю и передать параметром самого себя.
    var header = document.getElementsByTagName('h1');
    header[0].parentNode.removeChild(div[0]);
    //
    // Замена узлов
    header[0].parentNode.replaceChild(newText, header[0]); // удаляет дочерний узел и замещает его другим. Вызывается
    // относительно родительского узла. 1 пар - новый узел,
    // 2 пар - заменяемый узел.
    //
    //
    // Редко исп. Полезен для выполнения операций над множеством узлов. Подкласс объекта Node, он служит временным
    // контейнером для других узлов. Т.е. создаем объект(контейнер) DocumentFragment и помещаем в него различные узлы.
    // Со всеми ними можно работать как с одним большим узлом.
    var frag = document.createDocumentFragment();
    frag.appendChild(elem1);
    frag.appendChild(elem2);
    div.appendChild(frag);
    //
    //
    // Работа с формами.
    < input type = "text" name = "text_field_1" / >
    < / form >
    // У объекта document есть свойство forms. Данное свойство ссылается на объект HTML Collection, в котором
    // содержатся все формы данного документа. Хотя форму можно выбрать по тегу или id.
    document.forms.my_name // обратились к свойству формз и выбрали форму по аттр. name.
    document.forms[0] // или так
    // чтобы обратиться к конкретному полю input можно по именам
    document.forms.my_name.text_field_1; // вернет Object HTMLInputElement
    // обратиться к аттрибуту поля
    document.forms.my_name.text_field_1.type; // text
    // полуичть содержимое поля - свойство value
    document.forms.my_name.text_field_1.value;
    // Обращаться к элементам формы можно не используя их имена, а используя свойство elements, которое содержит все
    // елементы формы.
    document.forms.my_name.elements[0].value;
    // Радиокнопки и чекбоксы имеют одно имя и разное значение. Нам вернется объект, подобный массиву с элементами с
    // одинаковыми именами.
    < input type = "radio" name = "my_radio" / >
    < input type = "radio" name = "my_radio" / >
    document.my_name.elements.my_radio[0];
    // метод submit - выполняет отправку формы
    document.forms.my_name.submit();
    //
    //
    // Редко исп. свойства объекта Document
    document.images[0].src; // данное свойство images ссылается на Object HTML Collection, в котором содержаться
    // все изображения документа
    document.documentElement; // ссылается на корневой узел html
    document.body; // HTMLBodyElement
    document.title;
    document.anchors; // все якоря
    document.applets; // все java аплеты
    document.links; // все ссылки
    // методы
    document.createAttribute();
    document.createElement();
    document.createTextNode();
    1. копирайты отобразить жирным шрифтом, после нажатия на выполн функ. Исп replaceChild. заместить данный узел узлом
    стронг и внутрь его поместить данную строку
    2. создать функцию, которая пронумерует пункты меню. Добавить возлекаждого пункта его номер.
    3. выполнить сортировку в обратном порядке дочерних элементов узла body
    var b = document.body;
    var f = document.createDocumentFragment();
    while(b.lastChild)
    f . appendChild ( f . lastChild ) ;
    >
    b.innerHTML = f;
    4. выполнять перемещениепо DOM
    // События.
    // Тип события это строка, обозначающая тип выполненного действия. Событие это click. Приставка on
    // дописывается в соответствии с спецификацией.
    //
    // Чтобы заставить браузер выполнять код по клику можно добавить элементу аттрибут onclick="my_func()"
    //
    // События загрузки и готовности документа.
    // чтобы обратиться к событию и назначить обработчик события обратимся к одноименному свойству объекта
    window.onload = function() < . >// код сработает после полной загрузки страницы
    //
    // События форм
    onsubmit // данное событие срабатывает, когда происходит отправка формы
    onreset // нажатие на кнопку reset
    onchange // срабатывает когда выполняется изменение елементов форм (ввод данных) а затем убирается курсор.
    oninput // аналогично событию onchange. За исключением того, что данное событие срабатывает сразу же, как только
    // пользователь вводит символ в текстовое поле
    obj.onchange = function()
    alert ( obj . value ) ;
    >
    //
    onfocus // наведение курсора
    onblur // уведение курсора - потеря фокуса
    onfocusin - IE
    onfocusout - IE
    //
    //
    // События мыши
    onclick // когда срабатывает данное событие, создается объект у которого есть свойства. Чтобы их получить
    // надо передать параметр e(event) в анонимную функцию. В этот параметр попадает объект самого события.
    // altKey, shiftKey, ctrlKey вернут тру, если в момент клика была нажата соответствующая кнопка.
    // свойства clientX, clientY вернут координаты клика
    // свойство button показывает какой кнопкой кликали
    obj.onclick = function(e)
    alert ( e . altKey ) ;
    >
    onmousemove // срабатывает на движение мыши
    onmousedown // нажатие клавиши мыши
    onmouseup // пользователь отпускает нажатую клавишу
    oncontextmenu // кликая правой кнопкой мыши на экране пользователь открывает контекстное меню. Срабатывает событие.
    obj.oncontextmenu = function(e)
    return false ; // если функция-обработчик события возвращает false, то отменяется стандартное поведение
    // для данного события. Когда происходит клик правой кнопкой, браузер знает, что выхвано
    // контекстное меню. И если мы отменяем текущее значение по умолчанию данного события, то
    // вызов контекстного меню не проихойдет.
    >
    ondbclick // двойной клик. Редко исспольз.
    onmouseover // срабатывает когда пользователь перемещает курсор на выбранный нами элемент
    onmouseout // когда уводим курсор с элемента
    onmousewheel // когда выполняется прокрутка колесом мыши. может не работать в Firefox
    //
    //
    // События объекта window
    window.onload = function() < . >// код сработает после полной загрузки страницы
    window.onbeforeunload = function() < // срабатывает, перед тем как пользователь покидает документ
    return confirm ( 'Вы уходите?' ) ;
    >
    window.onfocus // срабатывает, когда окно получает фокус
    window.onblur // или его теряет. Актуально, когда вы создаете окна из определенного документа
    window.onresize // срабатывает при изменении размера окна
    window.onscroll // при прокрутке окна
    //
    //
    // События клавиатуры
    onkeypress // Нажатие клавиши. Является высокоуровневым событием. И ему соответствует объект, котоый содержит
    // информацию о введенном символе нажатой клавиши.
    e.keyCode // это ствойство содержит код нажатой клавиши
    obj.onkeypress = function(e)
    console . log ( e . keyCode ) ;
    >
    onkeyup // отжата
    onkeydown // срабатывает когда нажата клавиша
    //
    //
    // Если описать обработчик события onchange в html теге input. this переданный параметром функции означает
    // объект того элемента, у которого указан данный обработчик события. Его не нужно будет выбирать мы его сразу передаем.
    < input type = 'text' onclick = 'myFunc(this)' / >
    myFucn(param)
    console . log ( param . value ) ;
    >
    //
    //
    //
    // Фазы распространения события.
    < p onclick = "myFunc(this)" >p text
    < span onclick = "myFunc(this)" >span text < / span >
    < / p >
    < / div >
    myFunc(e)
    alert ( e . tagName ) ; // выведет имя тега. аналог nodeName
    >
    // При клике по спану отработает его обработчик события, затем p и родительского дива. Выведется 3 окна. span-p-div.
    // На данном примере мы видим фазу распространения события. А именно 3-ю фазу распространения события, которая
    // называется всплытие.
    document--родитель--родитель--целевой_элемент
    // Обработка события делится на 3 фазы
    // 1. перехват. Еще до того как вызывается событие в ЦЭ, т.е. пользователь кликнул мышью, но событие не
    // обработалось, начинается фаза перехвата события. Т.е. событие двигается от родительского элемента и проходит
    // ниже по узлам дерева DOM до ЦЭ таким образом, что событие можно перехватить в любом из родительских
    // элементов. В первую очередь вызываются перехватывающие обработчики самого верхнего элемента(window), затем
    // document, body и т.д. к ЦЭ, до тех пор пока не будут вызваны перехватывающие обработчики родителя ЦЭ.
    // Перехватывающие обработчики, которые зарегистрированы в самом ЦЭ при этом не вызывются
    // Модель распространения события бывает 2 видов:
    // 1.модель распространения событий-дерево DOM.
    // 2.модель распространения событий браузера IE. В IE8 и ниже первая фаза распространения события отсутствует.
    // Поэтому так сложилось, что фаза перехвата очень редко используется.
    // 2. вызов обработчика события в целевом элементе. Вызвалась назначенная функция.
    // 3. всплытие. Событие после обработки в ЦЭ начинает подниматься вверх по дереву DOM от ЦЭ к родителю
    // до самого верха.
    //
    //
    // Как можно одному событию назначить несколько функций обработчиков. Т.е. чтобы по клику
    // выполнилось сразу несколько функций.
    obj.addEventListener('click', myFunc, false); // данный метод позволяет регистрировать обработчики событий.
    // 1. параметр - тип события, для которго назначаем функции-обработчики. Имя события пишется без приставки "on".
    // 2. функция, которая должна вызываться при отработке события(без скобок. Если укажем скобки, это будет вызов,
    // а так только ссылка). Можно указать анонимную функцию.
    // 3. передается false или true. Обычно false. Если передаем true, функция обработчик будет зарегистрирована
    // как перехватывающий обработчик и будет вызывться в 1 фазе распространения события.
    //
    < h2 id = 'myId' >My text < / h2 >
    window.onload = function()
    h2 = document . getElementById ( 'myId' ) ;
    h2 . onclick = myFunc ; // так нельзя назначить несколько функций обработчиков.
    h2 . addEventListener ( 'click' , myFunc , false ) ;
    h2 . addEventListener ( 'click' , myFunc2 , false ) ;
    >
    myFunc(e)
    // когда отрабатывает addEventListener в переменную е приходит объект данного события.[object MouseEvent]
    console . log ( '1' ) ;
    >
    myFunc2(e)
    console . log ( '2' ) ;
    >
    //
    //
    // Кроссбраузерность.
    // метод для IE8 и ниже
    h2.attachEvent('onclick'. myFunc); // 2 параметра. Тип события с приставкой on.
    // Как написать кроссбраузерный скрипт. Для этого обычно пишется функция, которая будет выполнять роль регистратора
    // обработчика событий.
    function get_hendler(target, type, func)
    if ( target . addEventListener )
    target . addEventListener ( type , func , false ) ;
    >
    else if(target.attachEvent)
    target . attachEvent ( 'on' + type , func ) ;
    >
    >
    function myFunc ( e )
    e = e || window . event ;
    alert ( e ) ;
    >
    function myFunc2(e)
    e = e || window . event ;
    alert ( e ) ;
    >
    window.onload = function()
    get_hendler ( h2 , 'click' , myFunc ) ;
    get_hendler ( h2 , 'click' , myFunc2 ) ;
    >
    //
    //
    //
    // Как отменить действие по умолчанию для определенных элементов.
    < a href = 'http://ya.ru' onclick = 'myFunc' >link < / a >
    myFunc(e)
    e . preventDefault ( ) ;
    >
    // Что делать если мы хотим произвести над этой ссылкой какие-то действия по клику. Действия выполняться, но
    // будет совершен преход по ссылке.
    // У объекта события e есть метод
    e.preventDefault(); // отменяет действие по умолчанию для выбранного эл.
    //
    e.returnValue = false; // IE8 подобный эффект достигается с помощью
    myFunc(e)
    e = e || window . event ;
    if ( e . preventDefault ( ) )
    e . preventDefault ( )
    >
    else if(e.returnValue)
    e . returnValue = false ;
    >
    >
    //
    // также отменить действие по умолчанию
    //
    //
    // Методы позволяющие остановить распространение события.
    stopPropagation(); // прерывает распространене события. Вызывается у одного из родителей. IE8 не поддерж.
    window.event.cancelBubble = true; // для IE8
    removeEventListener() // удаляет фунцию обработчик из объекта. Применяется для временных обработч соб.
    detachEvent(); // для IE8
    // 1. разворачивающиеся меню
    //////////Лаврик//////////////
    // У каждого объекта есть методы свойства и события.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *