| {{JavaScript}} -- стандартный (де-факто) язык скриптования Web-страниц, выполняемый в браузере. По сей причине является наиболее используемым языком программирования, несмотря на значительные проблемы языка (поведение кода нередко оказывается неочевидным, разительно различается для разных типов, и даже может зависеть от используемого браузера -- написание кода, гарантированно работающего везде и всегда как задумано, задача весьма нетривиальная). Общую справку по стандарту JavaScript можно найти, в частности, [здесь|http://www.w3schools.com/jsref] и [здесь|https://developer.mozilla.org/en-US/docs/Web/JavaScript]. |
| |
| В браузерах реализована возможность использовать написанные на JavaScript интерпретаторы/трансляторы (в JS) для выполнения скриптов на других (более удобных) языках; также транслирование в JS может выполняться предварительно, как компиляция (в этом случае транслятор может быть написан не на JavaScript). Примеры: [CoffeeScript], [ClojureScript|Clojure]. |
| |
| Также виртуальные машины для выполнения JS существуют отдельно от браузеров ("headless WebKit"); они предназначены для автоматизированного тестирования JS-кода, и для повторного использования части кода на сервере (хотя в последнее время для этой цели нередко используются транслируемые на JS языки). На DL для тестирования JS используется [PhantomJS|http://phantomjs.org] версии [1.9.8|https://bitbucket.org/ariya/phantomjs/downloads]. |
| |
| (Внимание: запуск на DL выполняется внутри [скрипта|http://dl.gsu.by/images/agulenko/js/scripts/argrunner.js], изменяющего поведение по умолчанию: в частности, при ошибке работа PhantomJS завершается с кодом 1, а отсутствующие методы строк заменены эквивалентными реализациями.) |
| |
| Вместо компиляции производится проверка синтаксиса программой [JavaScript Lint|http://www.javascriptlint.com/download.htm] (основанной на JS-движке Firefox) со слегка изменённым набором правил ([заархивированная версия|http://dl.gsu.by/images/agulenko/js/jsl-conf.zip]). |
| |
| h2. Основы языка |
| |
| {code:java|title=типы} |
| true, false // boolean, булевский |
| null // null-объект |
| undefined // undefined, значение по умолчанию |
| 5, 5., .5, 0.5, Infinity, NaN // number, дробное число |
| 'a', "b", 'cd', "ef" // string, строка (UTF-16) |
| [], [1, 2, 'a', null, NaN] // Array, массив |
| {}, {key: 'value'}, ... // object, любой объект |
| {code} |
| Синтаксис заимствован большей частью из C, так что операторы похожи. |
| {code:java|title=операторы} |
| a == b, a != b // равенство/неравенство (с приведением типов) |
| a === b, a !== b // равенство/неравенство (по фактическому значению) |
| +a, a + b, a += b, a++ // плюс, сложение, инкрементация |
| -a, a - b, a -= b, a-- // минус, вычитание, декрементация |
| a * b, a / b, a % b // умножение, деление, остаток от деления |
| a *= b, a /= b, a %= b // присваивание с умножением/делением/остатком |
| a & b, a | b, a ^ b // побитовые and, or, xor (с приведением к целому) |
| a && b, a || b // логические and, or |
| a << b, a >> b // побитовый сдвиг |
| a <<= b, a >>= b // присваивание с побитовым сдвигом |
| (a ? b : c) // условное выражение |
| {code} |
| Правда, с операторами нужно быть осторожным -- их поведение может оказаться довольно неожиданным: |
| {code:java|title=примеры} |
| '5,6' == [5.0,6.] // true |
| '5, 6' != [5, 6] // true |
| 5 === 5.0000000000000001 // true |
| null !== undefined // true |
| [] + [] // "" |
| [] - [] // 0 |
| [] + {} // object |
| {} + [] // 0 - но не всегда |
| {} + {} // NaN - но не всегда |
| [5] + "9" // "59" |
| [5] - "9" // -4 |
| null || undefined || NaN || 0 // 0 |
| undefined || 0 || 9 || 0 // 9 |
| {code} |
| Общие правила синтаксиса похожи на C. |
| {code:java|title=конструкции языка} |
| // блок - работает как отдельная команда |
| something { // переносить не советую |
| do1(); |
| do2(); |
| } |
| |
| // переменные (глобальные - по возможности избегать) |
| p = 'a'; |
| q = "b"; |
| // переменные (локальные для функции) |
| var x = {value: 0}; |
| var |
| y = "1", |
| z = [y, 3]; |
| // переменные (локальные для блока; не поддерживаются PhantomJS) |
| let i = 0; |
| let |
| j = 4, |
| k = [3, j]; |
| // константы (запрещают присваивание; локальны для блока) |
| const |
| a = 9; |
| const |
| b = "8", |
| c = [b, NaN]; |
| |
| // условие |
| if (condition) |
| doSomething(); |
| else |
| doSomethingElse(); |
| switch (variable) { |
| case value1: |
| do1(); |
| break; |
| case value2: |
| case value3: |
| do2(); |
| break; |
| default: |
| do3(); |
| } |
| |
| // цикл |
| for (init(); condition; step()) |
| doStuff(i); |
| while (condition) |
| doSomething(); |
| do { |
| doSomething(); |
| } while (condition); |
| |
| // функция |
| function s (arg1, arg2) { |
| doThings([arg1, arg2]); |
| } |
| var func = function (args) { doThings(args) }; |
| const f = function fact (n) { |
| return ((n < 2) ? n : (n * fact(n-1))); |
| }; |
| {code} |
| |
| h2. Ввод-вывод (+PhantomJS) |
| |
| Для доступа к операциям ввода-вывода нужно использовать библиотеку PhantomJS: |
| {code:java|title=подключение модулей} |
| const |
| sys = require('system'), // модуль для взаимодействия с ОС |
| fs = require('fs'); // модуль для работы с файлами |
| {code} |
| Также имеется модуль под названием {{phantom}}, подключаемый автоматически. |
| |
| | Поскольку обычный JS-скрипт (в web-странице) никогда не "завершается", при решении задач на программирование требуется явно вызывать команду завершения: |
| | Поскольку обычный JS-скрипт (в web-странице) никогда не "завершается", при решении задач на программирование вызывается команда завершения: |
| {code:java} |
| phantom.exit(); |
| {code} |
| Поскольку в браузере JavaScript всегда подключён к (обычно скрытому) REPL, в нём есть команды вывода в консоль: |
| {code:java|title=встроенные команды вывода} |
| console.log(some, things); // стандартный вывод текста |
| console.error(message); // стандартный вывод ошибок |
| {code} |
| PhantomJS предоставляет ввод-вывод посредством файловых объектов: |
| {code:java|title=работа с файлами} |
| var |
| fin = fs.open("input.txt", 'r'), |
| s1 = fin.readLine(), // читает строку (до EOL) |
| s2 = fin.read(L), // читает 5 байт |
| s3 = fin.read(); // читает до EOL |
| fin.close(); |
| |
| var |
| fout = fs.open("output.txt", 'w'); |
| fout.write(s2); // выводит текст |
| fout.writeLine(s1); // выводит строку + EOL |
| fout.close(); |
| {code} |
| Для работы с консолью он предоставляет файловые объекты stdin, stdout и stderr: |
| {code:java|title=работа с консолью} |
| const s = sys.stdin.readLine(); |
| sys.stdout.writeLine(s); |
| sys.stderr.writeLine(s); |
| {code} |
| |
| h2. Примеры |
| |
| {code:java|title=a+b} |
| const sys = require('system'); |
| |
| function readAll (fin) { |
| const l = fin.readLine().split(' '); |
| return {a: parseInt(l[0]), |
| b: parseInt(l[1])}; |
| } |
| |
| function printAll (fout, res) { |
| fout.writeLine(res); |
| } |
| |
| calc = function (o) { return o.a + o.b }; |
| |
| printAll(sys.stdout, calc( readAll(sys.stdin) )); |
| | phantom.exit(); |
| {code} |
| или |
| {code:java|title=a+b (сокращённо)} |
| const sys = require('system'); |
| |
| const |
| l = sys.stdin.readLine().split(' '), |
| a = l[0], b = l[1]; |
| console.log(parseInt(a) + parseInt(b)); |
| | phantom.exit(); |
| {code} |