Синтаксис JavaScript - JavaScript syntax

Синтаксис в JavaScript является набором правил , которые определяют правильно структурированную программу JavaScript.

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

В стандартной библиотеке JavaScript отсутствует официальная стандартная функция вывода текста (за исключением document.write). Учитывая, что JavaScript в основном используется для написания сценариев на стороне клиента в современных веб-браузерах , и что почти все веб-браузеры предоставляют функцию предупреждения , предупреждение также можно использовать, но обычно не используется.

Происхождение

Брендан Эйх резюмировал происхождение синтаксиса в первом абзаце спецификации JavaScript 1.1 следующим образом:

JavaScript заимствует большую часть своего синтаксиса из Java , но также наследуется от Awk и Perl с некоторым косвенным влиянием Self в его системе прототипов объектов.

Основы

Чувствительность к регистру

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

Пример:

var a=5;
console.log(a); // 5
console.log(A); // throws a ReferenceError: A is not defined

Пробелы и точки с запятой

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

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

Пять проблемных токенов - это открытая скобка " ( ", открытая скобка " [ ", косая черта " / ", плюс " + " и минус " - ". Из них открытая скобка часто встречается в шаблоне выражения немедленно вызываемой функции , и открытая скобка встречается иногда, в то время как другие встречаются довольно редко. В спецификации приведен следующий пример:

a = b + c
(d + e).foo()

// Treated as:
//  a = b + c(d + e).foo();

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

Некоторые предлагают вместо использования ведущей точки с запятой в строках , начинающихся с « ( » или « [ », так что линия не случайно вместе с предыдущим. Это известно как оборонительной точкой с запятой , и особенно рекомендуется, потому что код может иначе стать неоднозначно при перестановке. Например:

a = b + c
;(d + e).foo()

// Treated as:
//  a = b + c;
//  (d + e).foo();

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

Пять ограниченных производств: return , throw , break , continue и пост-инкремент / декремент. Во всех случаях вставка точки с запятой не устраняет проблему, но делает синтаксис понятным, что упрощает обнаружение ошибки. return и throw принимают необязательное значение, а break и continue - необязательную метку. Во всех случаях рекомендуется оставлять значение или метку в той же строке, что и оператор. Чаще всего это проявляется в операторе return, где можно вернуть литерал большого объекта, который может быть случайно помещен с новой строки. Для постинкремента / декремента существует потенциальная двусмысленность с пре-инкрементом / декрементом, и снова рекомендуется просто оставить их в одной строке.

return
a + b;

// Returns undefined. Treated as:
//   return;
//   a + b;
// Should be written as:
//   return a + b;

Комментарии

Синтаксис комментариев такой же, как в C ++ , Swift и многих других языках.

// a short, one-line comment

/* this is a long, multi-line comment
  about my script. May it one day
  be great. */

/* Comments /* may not be nested */ Syntax error */

Переменные

Переменные в стандартном JavaScript не имеют прикрепленного типа , поэтому любое значение (каждое значение имеет тип) может быть сохранено в любой переменной. Начиная с ES6 , 6 - й версии языка, переменные могут быть объявлены varдля функции контекстные переменные, и letили constкоторые являются для уровня блока переменных. До ES6 переменные можно было объявлять только с помощью varоператора. Значения, присвоенные переменным, объявленным с constпомощью, нельзя изменить, но можно изменить его свойства. Идентификатор переменной должен начинаться с буквы, подчеркивания ( _ ) или знака доллара ( $ ), а последующие символы также могут быть цифрами ( 0–9 ). JavaScript чувствителен к регистру, поэтому символы верхнего регистра от «A» до «Z» отличаются от символов нижнего регистра от «a» до «z».

Начиная с JavaScript 1.5, в идентификаторах можно использовать буквы ISO 8859-1 или Unicode (или escape-последовательности \ uXXXX Unicode). В некоторых реализациях JavaScript знак at (@) может использоваться в идентификаторе, но это противоречит спецификациям и не поддерживается в новых реализациях.

Определение объема и подъем

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

С var, letи constзаявление, только декларация поднято; назначения не поднимаются. Таким образом, оператор в середине функции эквивалентен оператору объявления в верхней части функции и оператору присваивания в этой точке в середине функции. Это означает, что к значениям нельзя получить доступ до того, как они будут объявлены; прямая ссылка невозможна. Со значением переменной есть до ее инициализации. Переменные, объявленные с помощью или не могут быть доступны до тех пор, пока они не инициализированы, поэтому обращение к переменной вызовет ошибку. var x = 1var xx = 1varundefinedletconst

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

Так, например,

var func = function() { .. } // declaration is hoisted only
function func() { .. } // declaration and assignment are hoisted

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

Декларация и уступка

Переменные, объявленные вне области видимости, являются глобальными . Если переменная объявлена ​​в более высокой области видимости, к ней могут получить доступ дочерние области.

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

При назначении идентификатора JavaScript выполняет точно такой же процесс для получения этого идентификатора, за исключением того, что, если он не найден в глобальной области видимости , он создаст «переменную» в той области, в которой она была создана. Как следствие, никогда не объявленная переменная будет глобальной, если она назначена. Объявление переменной (с ключевым словом var) в глобальной области видимости (т.е. вне тела функции (или блока в случае let / const)), присвоение никогда не объявленного идентификатора или добавление свойства к глобальному объекту (обычно window ) приведет к также создайте новую глобальную переменную.

Обратите внимание, что строгий режим JavaScript запрещает присвоение необъявленной переменной, что позволяет избежать загрязнения глобального пространства имен.

Примеры

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

var x1 = 0; // A global variable, because it is not in any function
let x2 = 0; // Also global, this time because it is not in any block

function f() {
  var z = 'foxes', r = 'birds'; // 2 local variables
  m = 'fish'; // global, because it wasn't declared anywhere before

  function child() {
    var r = 'monkeys'; // This variable is local and does not affect the "birds" r of the parent function.
    z = 'penguins'; // Closure: Child function is able to access the variables of the parent function.
  }

  twenty = 20; // This variable is declared on the next line, but usable anywhere in the function, even before, as here
  var twenty;

  child();
  return x1 + x2; // We can use x1 and x2 here, because they are global
}

f();

console.log(z); // This line will raise a ReferenceError exception, because the value of z is no longer available
for (let i = 0; i < 10; i++) console.log(i);
console.log(i); // throws a ReferenceError: i is not defined
for (const i = 0; i < 10; i++) console.log(i); // throws a TypeError: Assignment to constant variable

const pi; // throws a SyntaxError: Missing initializer in const declaration

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

Язык JavaScript предоставляет шесть примитивных типов данных :

  • Неопределенный
  • Число
  • BigInt
  • Нить
  • Логический
  • Условное обозначение

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

Неопределенный

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

Примечание: undefined считается подлинным примитивным типом. Если не преобразовано явно, неопределенное значение может вести себя неожиданно по сравнению с другими типами, которые оцениваются как ложные в логическом контексте.

var test;                         // variable declared, but not defined, ...
                                  // ... set to value of undefined
var testObj = {};
console.log(test);                // test variable exists, but value not ...
                                  // ... defined, displays undefined
console.log(testObj.myProp);      // testObj exists, property does not, ...
                                  // ... displays undefined
console.log(undefined == null);   // unenforced type during check, displays true
console.log(undefined === null);  // enforce type during check, displays false

Примечание. Для undefined нет встроенного языкового литерала. Таким образом, это не надежный способ проверить, не определена ли переменная, потому что в версиях до ECMAScript 5 кто-то может писать . Более надежный подход - сравнить использование . (x === undefined)var undefined = "I'm defined now";(typeof x === 'undefined')

Такие функции не будут работать должным образом:

function isUndefined(x) { var u; return x === u; }             // like this...
function isUndefined(x) { return x === void 0; }               // ... or that second one
function isUndefined(x) { return (typeof x) === "undefined"; } // ... or that third one

Здесь вызов isUndefined(my_var)вызывает ошибку ReferenceError, если my_var - неизвестный идентификатор, тогда как нет. typeof my_var === 'undefined'

Число

Числа представлены в двоичном формате как двойные числа с плавающей запятой IEEE-754 . Хотя этот формат обеспечивает точность почти до 16 значащих цифр , он не всегда может точно представлять действительные числа, включая дроби.

Это становится проблемой при сравнении или форматировании чисел. Например:

console.log(0.2 + 0.1 === 0.3); // displays false
console.log(0.94 - 0.01);       // displays 0.9299999999999999

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

Числа могут быть указаны в любом из следующих обозначений:

345;    // an "integer", although there is only one numeric type in JavaScript
34.5;   // a floating-point number
3.45e2; // another floating-point, equivalent to 345
0b1011; // a binary integer equal to 11
0o377;   // an octal integer equal to 255
0xFF;   // a hexadecimal integer equal to 255, digits represented by the ...
        // ... letters A-F may be upper or lowercase

Также в ES2021 появился числовой разделитель _ (подчеркивание):

// Note: Wikipedia syntax doesn't support numeric separators yet
1_000_000_000;    // Used with big numbers
1_000_000.5;      // Support with decimals
1_000e1_000;      // Support with exponents

// Support with binary, octals and hex
0b0000_0000_0101_1011;
0o0001_3520_0237_1327;
0xFFFF_FFFF_FFFF_FFFE;

// But you can't use them next to a non-digit number part, or at the start or end
_12; // Variable is not defined (the underscore makes it a variable identifier)
12_; // Syntax error (cannot be at the end of numbers)
12_.0; // Syntax error (doesn't make sense to put a separator next to the decimal point)
12._0; // Syntax error
12e_6; // Syntax error (next to "e", a non-digit. Doesn't make sense to put a separator at the start)
1000____0000; // Syntax error (next to "_", a non-digit. Only 1 separator at a time is allowed

Экстенты + ∞ , −∞ и NaN (не число) числового типа могут быть получены с помощью двух программных выражений:

Infinity; // positive infinity (negative obtained with -Infinity for instance)
NaN;      // The Not-A-Number value, also returned as a failure in ...
          // ... string-to-number conversions

Бесконечность и NaN - это числа:

typeof Infinity;   // returns "number"
typeof NaN;        // returns "number"

Эти три специальных значения соответствуют и ведут себя так, как их описывает IEEE-754 .

Конструктор Number (используемый как функция) или унарный + или - могут использоваться для выполнения явного числового преобразования:

var myString = "123.456";
var myNumber1 = Number(myString);
var myNumber2 = +myString;

При использовании в качестве конструктора создается числовой объект- оболочка (хотя от него мало пользы):

myNumericWrapper = new Number(123.456);

Однако NaN не равен самому себе:

const nan = NaN;
console.log(NaN == NaN);        // false
console.log(NaN === NaN);       // false
console.log(NaN !== NaN);       // true
console.log(nan !== nan);       // true

// You can use the isNaN methods to check for NaN
console.log(isNaN("converted to NaN"));     // true
console.log(isNaN(NaN));                    // true
console.log(Number.isNaN("not converted")); // false
console.log(Number.isNaN(NaN));             // true

BigInt

BigInts можно использовать для сколь угодно больших целых чисел . В частности, целые числа больше 2 53 - 1, которые являются наибольшим числом, которое JavaScript может надежно представить с помощью примитива Number и представленного константой Number.MAX_SAFE_INTEGER.

При делении BigInts, результаты усечены .

Нить

Строка в JavaScript представляет собой последовательность символов. В JavaScript строки можно создавать напрямую (как литералы), помещая серию символов между двойными (") или одинарными (') кавычками. Такие строки должны быть записаны в одной строке, но могут включать в себя экранированные символы новой строки (например, \ n). Стандарт JavaScript позволяет использовать символы обратной кавычки (`, акцент или обратную кавычку) для цитирования многострочных буквальных строк, но с 2016 года это поддерживается только в некоторых браузерах: Firefox и Chrome, но не в Internet Explorer 11.

var greeting = "Hello, World!";
var anotherGreeting = 'Greetings, people of Earth.';

Доступ к отдельным символам в строке можно получить с помощью метода charAt (предоставляемого String.prototype ). Это предпочтительный способ доступа к отдельным символам в строке, потому что он также работает в несовременных браузерах:

var h = greeting.charAt(0);

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

var h = greeting[0];

Однако строки JavaScript неизменяемы :

greeting[0] = "H"; // Fails.

Применение оператора равенства ("==") к двум строкам возвращает истину, если строки имеют одинаковое содержимое, что означает: одинаковой длины и одинаковой последовательности символов (регистр важен для алфавитов). Таким образом:

var x = "World";
var compare1 = ("Hello, " +x == "Hello, World"); // Here compare1 contains true.
var compare2 = ("Hello, " +x == "hello, World"); // Here compare2 contains  ...
                                                 // ... false since the ...
                                                 // ... first characters ...
                                                 // ... of both operands ...
                                                 // ... are not of the same case.

Цитаты одного типа не могут быть вложены, если они не экранированы .

var x = '"Hello, World!" he said.'; // Just fine.
var x = ""Hello, World!" he said."; //  Not good.
var x = "\"Hello, World!\" he said."; // Works by escaping " with \"

Конструктор String создает строковый объект (объект, заключающий строку):

var greeting = new String("Hello, World!");

У этих объектов есть метод valueOf, возвращающий заключенную в них примитивную строку:

var s = new String("Hello !");
typeof s; // Is 'object'.
typeof s.valueOf(); // Is 'string'.

Равенство между двумя объектами String не работает так, как со строковыми примитивами:

var s1 = new String("Hello !");
var s2 = new String("Hello !");
s1 == s2; // Is false, because they are two distinct objects.
s1.valueOf() == s2.valueOf(); // Is true.

Логический

JavaScript предоставляет логический тип данных с истинными и ложными литералами. Оператор typeof возвращает строку "boolean" для этих примитивных типов . При использовании в логическом контексте 0 , -0 , null , NaN , undefined и пустая строка ( "" ) оцениваются как ложные из-за автоматического приведения типов . Все остальные значения ( дополнение к предыдущему списку) оцениваются как истинные , включая строки «0» , «false» и любой объект.

Преобразование типов

Автоматического приведения типа операторами сравнения равенства ( ==и !=) можно избежать, используя операторы сравнения с проверкой типа ( ===и !==).

Когда требуется преобразование типа, JavaScript преобразует логические , числовые , строковые или объектные операнды следующим образом:

Число и строка
Строка преобразуется в числовое значение. JavaScript пытается преобразовать строковый числовой литерал в значение числового типа. Во-первых, математическое значение получается из строкового числового литерала. Затем это значение округляется до ближайшего значения числового типа.
Логический
Если один из операндов является логическим, логический операнд преобразуется в 1, если он истинен , или в 0, если он ложен .
Объект
Если объект сравнивается с числом или строкой, JavaScript пытается вернуть значение по умолчанию для объекта. Объект преобразуется в примитивное строковое или числовое значение с помощью методов .valueOf () или .toString () объекта. Если это не удается, генерируется ошибка времени выполнения.

Дуглас Крокфорд защищает термины « правдивость » и « ложь » для описания поведения значений различных типов при оценке в логическом контексте, особенно в отношении крайних случаев. Бинарные логические операторы возвращали логическое значение в ранних версиях JavaScript, но теперь вместо этого они возвращают один из операндов. Возвращается левый операнд, если он может быть оценен как: false в случае конъюнкции : ( a && b) или как истина в случае дизъюнкции : ( a || b); в противном случае возвращается правый операнд. Автоматическое приведение типа операторами сравнения может отличаться для случаев смешанных логических и числовых операндов (включая строки, которые могут быть оценены как число, или объекты, которые могут быть оценены как такая строка), потому что логический операнд будет сравниваться как числовое значение. Это может быть неожиданно. Выражение может быть явным образом преобразовано в логический примитив, удвоив оператор логического отрицания : ( !! ), используя функцию Boolean () или условный оператор : ( c ? t : f).

// Automatic type coercion
console.log(true  ==   2 ); // false... true  → 1 !== 2 ←  2
console.log(false ==   2 ); // false... false → 0 !== 2 ←  2
console.log(true  ==   1 ); // true.... true  → 1 === 1 ←  1
console.log(false ==   0 ); // true.... false → 0 === 0 ←  0
console.log(true  ==  "2"); // false... true  → 1 !== 2 ← "2"
console.log(false ==  "2"); // false... false → 0 !== 2 ← "2"
console.log(true  ==  "1"); // true.... true  → 1 === 1 ← "1"
console.log(false ==  "0"); // true.... false → 0 === 0 ← "0"
console.log(false ==  "" ); // true.... false → 0 === 0 ← ""
console.log(false ==  NaN); // false... false → 0 !== NaN

console.log(NaN == NaN); // false...... NaN is not equivalent to anything, including NaN.

// Type checked comparison (no conversion of types and values)
console.log(true === 1); // false...... data types do not match

// Explicit type coercion
console.log(true === !!2);   // true.... data types and values match
console.log(true === !!0);   // false... data types match, but values differ
console.log( 1  ? true : false); // true.... only ±0 and NaN are "falsy" numbers
console.log("0" ? true : false); // true.... only the empty string is "falsy"
console.log(Boolean({}));    // true.... all objects are "truthy"

Оператор new может использоваться для создания оболочки объекта для логического примитива. Однако оператор typeof не возвращает логическое значение для оболочки объекта, он возвращает объект . Поскольку все объекты оцениваются как истинные , для получения обернутого значения необходимо использовать такой метод, как .valueOf () или .toString () . Для явного принуждения к типу Boolean Mozilla рекомендует использовать функцию Boolean () (без new ) вместо объекта Boolean.

var b = new Boolean(false);   // Object  false {}
var t = Boolean(b);           // Boolean true
var f = Boolean(b.valueOf()); // Boolean false
var n = new Boolean(b);       // Not recommended
n = new Boolean(b.valueOf()); // Preferred

if (0 || -0 || "" || null || undefined || b.valueOf() || !new Boolean() || !t) {
  console.log("Never this");
} else if ([] && {} && b && typeof b === "object" && b.toString() === "false") {
  console.log("Always this");
}

Условное обозначение

Новое в ECMAScript6. Символ представляет собой уникальный идентификатор и неизменный.

Пример:

var x = Symbol(1);
var y = Symbol(1);
x === y; // => false

var symbolObject = {};
var normalObject = {};

// since x and y are unique,
// they can be used as unique keys in an object
symbolObject[x] = 1;
symbolObject[y] = 2;

symbolObject[x]; // => 1
symbolObject[y]; // => 2

// as compared to normal numeric keys
normalObject[1] = 1;
normalObject[1] = 2; // overrides the value of 1

normalObject[1]; // => 2

// changing the value of x does not change the key stored in the object
x = Symbol(3);
symbolObject[x]; // => undefined

// changing x back just creates another unique Symbol
x = Symbol(1);
symbolObject[x]; // => undefined

Есть также известные символы .

Один из которых Symbol.iterator; если что-то реализуется Symbol.iterator, это повторяется:

let x = [1, 2, 3, 4]; // x is an Array
x[Symbol.iterator] === Array.prototype[Symbol.iterator]; // and Arrays are iterable

const xIterator = x[Symbol.iterator](); // The [Symbol.iterator] function should provide an iterator for x
xIterator.next(); // { value: 1, done: false }
xIterator.next(); // { value: 2, done: false }
xIterator.next(); // { value: 3, done: false }
xIterator.next(); // { value: 4, done: false }
xIterator.next(); // { value: undefined, done: true }
xIterator.next(); // { value: undefined, done: true }

// for..of loops automatically iterate values
for (const value of x) {
   console.log(value); // 1 2 3 4
}

// Sets are also iterable:
[Symbol.iterator] in Set.prototype; // true

for (const value of new Set(['apple', 'orange'])) {
   console.log(value); // "apple" "orange"
}

Родные объекты

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

Множество

Массив представляет собой объект JavaScript , прототип из массива конструктора , специально предназначенного для хранения значений данных , индексированных целых ключами. Массивы, в отличие от базового типа Object, имеют прототипы с методами и свойствами, чтобы помочь программисту в повседневных задачах (например, объединение , срезание и отправка ).

Как и в семействе C , массивы используют схему индексации с отсчетом от нуля: значение, вставленное в пустой массив с помощью метода push, занимает 0-й индекс массива.

var myArray = [];            // Point the variable myArray to a newly ...
                             // ... created, empty Array
myArray.push("hello World"); // Fill the next empty index, in this case 0
console.log(myArray[0]);           // Equivalent to console.log("hello World");

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

К элементам Array s можно получить доступ, используя обычную нотацию доступа к свойствам объекта:

myArray[1];  // the 2nd item in myArray
myArray["1"];

Вышеупомянутые два эквивалентны. Невозможно использовать обозначение «точка» или строки с альтернативными представлениями числа:

myArray.1;     // syntax error
myArray["01"]; // not the same as myArray[1]

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

let myArray;

// Array literals
myArray = [1, 2]; // length of 2
myArray = [1, 2,]; // same array - You can also have an extra comma at the end

// It's also possible to not fill in parts of the array
myArray = [0, 1, /* hole */, /* hole */, 4, 5]; // length of 6
myArray = [0, 1, /* hole */, /* hole */, 4, 5,]; // same array
myArray = [0, 1, /* hole */, /* hole */, 4, 5, /* hole */,]; // length of 7

// With the constructor
myArray = new Array(0, 1, 2, 3, 4, 5); // length of 6
myArray = new Array(365);              // an empty array with length 365

Массивы реализованы так, что только определенные элементы используют память; они представляют собой « разреженные массивы ». Настройка и использует пространство только для этих двух элементов, как и любой другой объект. Длина массива будет по- прежнему , как сообщалось 58. максимальная длина массива составляет 4294967295 , который соответствует 32-битного двоичного числа (11111111111111111111111111111111) 2 . myArray[10] = 'someThing'myArray[57] = 'somethingOther'

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

dog = {color: "brown", size: "large"};
dog["color"]; // results in "brown"
dog.color;    // also results in "brown"

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

cats = [{color: "brown", size: "large"},
    {color: "black", size: "small"}];
cats[0]["size"];      // results in "large"

dogs = {rover: {color: "brown", size: "large"},
    spot: {color: "black", size: "small"}};
dogs["spot"]["size"]; // results in "small"
dogs.rover.color;     // results in "brown"

Дата

Объект Date хранит счетчик миллисекунд со знаком, где ноль представляет 1970-01-01 00:00:00 UT и диапазон ± 10 8 дней. Есть несколько способов предоставить аргументы конструктору Date . Обратите внимание, что месяцы отсчитываются от нуля.

new Date();                       // create a new Date instance representing the current time/date.
new Date(2010, 2, 1);             // create a new Date instance representing 2010-Mar-01 00:00:00
new Date(2010, 2, 1, 14, 25, 30); // create a new Date instance representing 2010-Mar-01 14:25:30
new Date("2010-3-1 14:25:30");    // create a new Date instance from a String.

Предоставляются методы для извлечения полей, а также полезный toString :

var d = new Date(2010, 2, 1, 14, 25, 30); // 2010-Mar-01 14:25:30;

// Displays '2010-3-1 14:25:30':
console.log(d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' '
    + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds());

// Built-in toString returns something like 'Mon Mar 01 2010 14:25:30 GMT-0500 (EST)':
console.log(d);

Ошибка

Пользовательские сообщения об ошибках могут быть созданы с использованием класса Error :

throw new Error("Something went wrong.");

Их можно перехватить с помощью блоков try ... catch ... finally, как описано в разделе, посвященном обработке исключений .

Математика

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

Некоторые константы, содержащиеся в объекте Math
Имущество Возвращаемое значение
округлено до 5 цифр.
Описание
Math.E 2,7183 e : основание натурального логарифма
Math.LN2 0,69315 Натуральный логарифм 2
Math.LN10 2,3026 Натуральный логарифм 10
Math.LOG2E 1,4427 Логарифм по основанию 2 числа e
Math.LOG10E 0,43429 Логарифм по основанию 10 числа e
Math.PI 3,14159 π : окружность / диаметр круга
Math.SQRT1_2 0,70711 Корень квадратный из ½
Math.SQRT2 1,4142 Корень квадратный из 2
Методы объекта Math
Пример Возвращаемое значение
округлено до 5 цифр.
Описание
Math.abs (-2,3) 2.3 Абсолютная величина
Math.acos (Math.SQRT1_2) 0,78540 рад. = 45 ° Арккосин
Math.asin (Math.SQRT1_2) 0,78540 рад. = 45 ° Арксинус
Математический атан (1) 0,78540 рад. = 45 ° Полукруг арктангенс (- π / 2 до + π / 2)
Math.atan2 (-3,7, -3,7) -2,3562 рад. = -135 ° Арктангенс всего круга (от - π до + π )
Math.ceil (1.1) 2 Потолок: округлить до наименьшего целого числа ≥ аргумента
Math.cos (Math.PI / 4) 0,70711 Косинус
Math.exp (1) 2,7183 Экспоненциальная функция : e в этой степени
Математический пол (1.9) 1 Этаж: округлить до наибольшего целого числа ≤ аргумент
Math.log (Math.E) 1 Натуральный логарифм, основание е
Math.max (1, -2) 1 Максимум: (x> y)? х: у
Math.min (1, -2) -2 Минимум: (x <y)? х: у
Math.pow (-3, 2) 9 Возведение в степень (в степени): Math.pow (x, y) дает x y
Math.random () например, 0,17068 Псевдослучайное число от 0 (включительно) до 1 (исключая)
Математический круг (1.5) 2 Округлить до ближайшего целого числа; половинные дроби округляются в большую сторону (например, 1,5 округления до 2)
Math.sin (Math.PI / 4) 0,70711 Синус
Math.sqrt (49) 7 Квадратный корень
Math.tan (Math.PI / 4) 1 Касательная

Регулярное выражение

/expression/.test(string);     // returns Boolean
"string".search(/expression/); // returns position Number
"string".replace(/expression/, replacement);

// Here are some examples
if (/Tom/.test("My name is Tom")) console.log("Hello Tom!");
console.log("My name is Tom".search(/Tom/));          // == 11 (letters before Tom)
console.log("My name is Tom".replace(/Tom/, "John")); // == "My name is John"

Классы персонажей

// \d  - digit
// \D  - non digit
// \s  - space
// \S  - non space
// \w  - word char
// \W  - non word
// [ ] - one of
// [^] - one not of
//  -  - range

if (/\d/.test('0'))                   console.log('Digit');
if (/[0-9]/.test('6'))                console.log('Digit');
if (/[13579]/.test('1'))              console.log('Odd number');
if (/\S\S\s\S\S\S\S/.test('My name')) console.log('Format OK');
if (/\w\w\w/.test('Tom'))             console.log('Hello Tom');
if (/[a-zA-Z]/.test('B'))             console.log('Letter');

Соответствие символов

// A...Z a...z 0...9  - alphanumeric
// \u0000...\uFFFF    - Unicode hexadecimal
// \x00...\xFF        - ASCII hexadecimal
// \t                 - tab
// \n                 - new line
// \r                 - CR
// .                  - any character
// |                  - OR

if (/T.m/.test('Tom')) console.log ('Hi Tom, Tam or Tim');
if (/A|B/.test("A"))  console.log ('A or B');

Повторители

// ?   - 0 or 1 match
// *   - 0 or more
// +   - 1 or more
// {n}   - exactly n
// {n,}  - n or more
// {0,n} - n or less
// {n,m} - range n to m

if (/ab?c/.test("ac"))       console.log("OK"); // match: "ac", "abc"
if (/ab*c/.test("ac"))       console.log("OK"); // match: "ac", "abc", "abbc", "abbbc" etc.
if (/ab+c/.test("abc"))      console.log("OK"); // match: "abc", "abbc", "abbbc" etc.
if (/ab{3}c/.test("abbbc"))  console.log("OK"); // match: "abbbc"
if (/ab{3,}c/.test("abbbc")) console.log("OK"); // match: "abbbc", "abbbbc", "abbbbbc" etc.
if (/ab{1,3}c/.test("abc"))  console.log("OK"); // match: "abc", "abbc", "abbbc"

Якоря

// ^  - string starts with
// $  - string ends with

if (/^My/.test("My name is Tom"))   console.log ("Hi!");
if (/Tom$/.test("My name is Tom"))  console.log ("Hi Tom!");

Подвыражение

// ( )  - groups characters

if (/water(mark)?/.test("watermark")) console.log("Here is water!"); // match: "water", "watermark",
if (/(Tom)|(John)/.test("John"))      console.log("Hi Tom or John!");

Флаги

// /g  - global
// /i  - ignore upper/lower case
// /m  - allow matches to span multiple lines

console.log("hi tom!".replace(/Tom/i, "John"));  // == "hi John!"
console.log("ratatam".replace(/ta/, "tu"));      // == "ratutam"
console.log("ratatam".replace(/ta/g, "tu"));     // == "ratutum"

Продвинутые методы

my_array = my_string.split(my_delimiter);
// example
my_array = "dog,cat,cow".split(",");      // my_array==["dog","cat","cow"];

my_array = my_string.match(my_expression);
// example
my_array = "We start at 11:30, 12:15 and 16:45".match(/\d\d:\d\d/g); // my_array==["11:30","12:15","16:45"];

Группы захвата

var myRe = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})/;
var results = myRe.exec("The date and time are 2009-09-08 09:37:08.");
if (results) {
  console.log("Matched: " + results[0]); // Entire match
  var my_date = results[1]; // First group == "2009-09-08"
  var my_time = results[2]; // Second group == "09:37:08"
  console.log("It is " + my_time + " on " + my_date);
} else console.log("Did not find a valid date!");

Функция

Каждая функция в JavaScript является экземпляром конструктора Function :

// x, y is the argument. 'return x + y' is the function body, which is the last in the argument list.
var add = new Function('x', 'y', 'return x + y');
add(1, 2); // => 3

Вышеупомянутая функция добавления также может быть определена с помощью выражения функции:

var add = function(x, y) {
  return x + y;
};
add(1, 2); // => 3

В ES6 был добавлен синтаксис стрелочной функции, что позволило функциям, возвращающим значение, быть более краткими. Они также сохраняют this глобального объекта вместо того, чтобы наследовать его от того места, где он был вызван / от того, где он был вызван, в отличие от выражения function () {} .

var add = (x, y) => {return x + y;};
// values can also be implicitly returned (i.e. no return statement is needed)
var addImplicit = (x, y) => x + y;

add(1, 2); // => 3
addImplicit(1, 2) // => 3

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

function add(x, y) {
  return x + y;
}
add(1, 2); // => 3

Подъем позволяет использовать функцию до ее «объявления»:

add(1, 2); // => 3, not a ReferenceError
function add(x, y) {
  return x + y;
}

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

function subtract(x, y) {
  return x - y;
}

console.log(subtract.length); // => 2, arity of the function (number of arguments)
console.log(subtract.toString());

/*
"function subtract(x, y) {
  return x - y;
}"
*/

Операторы

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

// Concatenate 2 strings
console.log('He' + 'llo'); // displays Hello

// Add two numbers
console.log(2 + 6);  // displays 8

// Adding a number and a string results in concatenation (from left to right)
console.log(2 + '2');    // displays 22
console.log('$' + 3 + 4);  // displays $34, but $7 may have been expected
console.log('$' + (3 + 4)); // displays $7
console.log(3 + 4 + '7'); // displays 77, numbers stay numbers until a string is added

// Convert a string to a number using the unary plus
console.log(+'2' === 2); // displays true
console.log(+'Hello'); // displays NaN

Точно так же перегружен оператор '*': он может преобразовывать строку в число.

console.log(2 + '6'*1);  // displays 8
console.log(3*'7'); // 21
console.log('3'*'7'); // 21
console.log('hello'*'world'); // displays NaN

Арифметика

JavaScript поддерживает следующие бинарные арифметические операторы :

+ добавление
- вычитание
* умножение
/ деление (возвращает значение с плавающей запятой)
% по модулю (возвращает остаток)
** возведение в степень

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

+ унарное преобразование строки в число
- унарное отрицание (меняет знак)
++ инкремент (может быть префиксным или постфиксным)
- декремент (может быть префиксным или постфиксным)
var x = 1;
console.log(++x); // x becomes 2; displays 2
console.log(x++); // displays 2; x becomes 3
console.log(x);  // x is 3; displays 3
console.log(x--); //  displays 3; x becomes 2
console.log(x);  //  displays 2; x is 2
console.log(--x); //  x becomes 1; displays 1

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

var x = 17;
console.log(x%5); // displays 2
console.log(x%6); // displays 5
console.log(-x%5); // displays -2
console.log(-x%-5); // displays -2
console.log(x%-5); // displays 2

Чтобы всегда возвращать неотрицательное число, повторно добавьте модуль и снова примените оператор по модулю:

var x = 17;
console.log((-x%5+5)%5); // displays 3

Назначение

знак равно назначать
+ = добавить и назначить
знак равно вычесть и присвоить
знак равно умножить и присвоить
знак равно разделить и назначить
знак равно по модулю и присвоить
знак равно возведение в степень и назначить

Назначение из примитивных типов

var x = 9;
x += 1; 
console.log(x); // displays: 10
x *= 30;
console.log(x); // displays: 300
x /= 6;
console.log(x); // displays: 50
x -= 3;
console.log(x); // displays: 47
x %= 7;
console.log(x); // displays: 5

Присвоение типов объектов

/**
 * To learn JavaScript objects...
 */
var object_1 = {a: 1};		// assign reference of newly created object to object_1
var object_2 = {a: 0};
var object_3 = object_2;	// object_3 references the same object as object_2 does
	 
object_3.a = 2;
message();	        	// displays 1 2 2
	 
object_2 = object_1;		// object_2 now references the same object as object_1
	        	        // object_3 still references what object_2 referenced before
message();		        // displays 1 1 2
	 
object_2.a = 7;  	        // modifies object_1
message();		        // displays 7 7 2

object_3.a = 5;                 // object_3 doesn't change object_2
message();	                // displays 7 7 5

object_3 = object_2;	
object_3.a=4;                  // object_3 changes object_1 and object_2
message();                     // displays 4 4 4

/**
 * Prints the console.log message
 */
function message() {
	console.log(object_1.a + " " + object_2.a + " " + object_3.a);
}

Назначение деструктуризации

В JavaScript Mozilla, начиная с версии 1.7, деструктурирующее присваивание позволяет назначать части структур данных сразу нескольким переменным. Левая часть присваивания - это шаблон, который напоминает произвольно вложенный литерал объекта / массива, содержащий l-lvalue на своих концах, которые должны получить подструктуры присвоенного значения.

var a, b, c, d, e;
[a, b, c] = [3, 4, 5];
console.log(a + ',' + b + ',' + c); // displays: 3,4,5
e = {foo: 5, bar: 6, baz: ['Baz', 'Content']};
var arr = [];
({baz: [arr[0], arr[3]], foo: a, bar: b}) = e;
console.log(a + ',' + b + ',' + arr);	// displays: 5,6,Baz,,,Content
[a, b] = [b, a];		// swap contents of a and b
console.log(a + ',' + b);		// displays: 6,5

[a, b, c] = [3, 4, 5]; // permutations
[a, b, c] = [b, c, a];
console.log(a + ',' + b + ',' + c); // displays: 4,5,3

Оператор разворота / отдыха

Стандарт ECMAScript 2015 вводит оператор « ... » для связанных понятий «синтаксис распространения» и «остальные параметры».

Синтаксис Spread предоставляет еще один способ деструктуризации массивов. Он указывает, что элементы в указанном массиве должны использоваться как параметры в вызове функции или элементы в литерале массива.

Другими словами, « ... » преобразует « [... foo] » в « [foo [0], foo [1], foo [2]] » и « this.bar (... foo); «в» this.bar (foo [0], foo [1], foo [2]); ».

var a = [1, 2, 3, 4];

// It can be used multiple times in the same expression
var b = [...a, ...a]; // b = [1, 2, 3, 4, 1, 2, 3, 4];

// It can be combined with non-spread items.
var c = [5, 6, ...a, 7, 9]; // c = [5, 6, 1, 2, 3, 4, 7, 9];

// For comparison, doing this without the spread operator 
// creates a nested array.
var d = [a, a]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]]

// It works the same with function calls
function foo(arg1, arg2, arg3) {
    console.log(arg1 + ':' + arg2 + ':' + arg3);
}

// You can use it even if it passes more parameters than the function will use
foo(...a); // "1:2:3" → foo(a[0], a[1], a[2], a[3]);

// You can mix it with non-spread parameters
foo(5, ...a, 6); // "5:1:2" → foo(5, a[0], a[1], a[2], a[3], 6);

// For comparison, doing this without the spread operator
// assigns the array to arg1, and nothing to the other parameters.
foo(a); // "1,2,3,4:undefined:undefined"

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

function foo(a, b, ...c) {
    console.log(c.length);
}

foo(1, 2, 3, 4, 5); // "3" → c = [3, 4, 5]
foo('a', 'b'); // "0" → c = []

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

Оператор ... может использоваться только с объектами Array . (Однако есть предложение расширить его до Object в будущем стандарте ECMAScript.)

Сравнение

== равный
знак равно не равный
> больше чем
> = больше или равно
< меньше, чем
<= меньше или равно
=== идентичные (одинаковые и однотипные)
! == не идентичный

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

var obj1 = {a: 1};
var obj2 = {a: 1};
var obj3 = obj1;
console.log(obj1 == obj2);  //false
console.log(obj3 == obj1);  //true
console.log(obj3 === obj1); //true

См. Также String .

Логический

JavaScript предоставляет четыре логических оператора:

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

  • Строки: "" , '' ,
  • Числа: 0 , -0 , NaN ,
  • Специальные: null , undefined ,
  • Логическое: ложь .

Логическая функция может использоваться для явного преобразования в примитив типа Boolean :

// Only empty strings return false
console.log(Boolean("")      === false);
console.log(Boolean("false") === true);
console.log(Boolean("0")     === true);

// Only zero and NaN return false
console.log(Boolean(NaN) === false);
console.log(Boolean(0)   === false);
console.log(Boolean(-0)  === false); // equivalent to -1*0
console.log(Boolean(-2)  === true);

// All objects return true
console.log(Boolean(this) === true);
console.log(Boolean({})   === true);
console.log(Boolean([])   === true);

// These types return false
console.log(Boolean(null)      === false);
console.log(Boolean(undefined) === false); // equivalent to Boolean()

Оператор NOT оценивает свой операнд как логическое значение и возвращает отрицание. Использование оператора дважды подряд в качестве двойного отрицательного значения явно преобразует выражение в примитив типа Boolean:

console.log( !0 === Boolean(!0));
console.log(Boolean(!0) === !!1);
console.log(!!1 === Boolean(1));
console.log(!!0 === Boolean(0));
console.log(Boolean(0) === !1);
console.log(!1 === Boolean(!1));
console.log(!"" === Boolean(!""));
console.log(Boolean(!"") === !!"s");
console.log(!!"s" === Boolean("s"));
console.log(!!"" === Boolean(""));
console.log(Boolean("") === !"s");	
console.log(!"s" === Boolean(!"s"));

Тернарный оператор также может использоваться для явного преобразования:

console.log([] == false); console.log([] ? true : false); // “truthy”, but the comparison uses [].toString()
console.log([0] == false); console.log([0]? true : false); // [0].toString() == "0"
console.log("0" == false); console.log("0"? true : false); // "0" → 0 ... (0 == 0) ... 0 ← false
console.log([1] == true); console.log([1]? true : false); // [1].toString() == "1"
console.log("1" == true); console.log("1"? true : false); // "1" → 1 ... (1 == 1) ... 1 ← true
console.log([2] != true); console.log([2]? true : false); // [2].toString() == "2"
console.log("2" != true); console.log("2"? true : false); // "2" → 2 ... (2 != 1) ... 1 ← true

Выражения, использующие такие функции, как пост-инкремент ( i ++ ), имеют ожидаемый побочный эффект . JavaScript обеспечивает оценку выражений коротким замыканием ; правый операнд выполняется только в том случае, если левого операнда недостаточно для определения значения выражения.

console.log(a || b);  // When a is true, there is no reason to evaluate b.
console.log(a && b);  // When a is false, there is no reason to evaluate b.
console.log(c ? t : f); // When c is true, there is no reason to evaluate f.

В ранних версиях JavaScript и JScript двоичные логические операторы возвращали логическое значение (как и большинство языков программирования, производных от C). Однако все современные реализации вместо этого возвращают один из своих операндов:

console.log(a || b); // if a is true, return a, otherwise return b
console.log(a && b); // if a is false, return a, otherwise return b

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

var s = t || "(default)"; // assigns t, or the default value, if t is null, empty, etc.

Логическое присвоение

знак равно Нулевое присвоение
|| = Логика или назначение
знак равно Логика и назначение

Побитовое

JavaScript поддерживает следующие двоичные побитовые операторы :

& А ТАКЖЕ
| ИЛИ
^ XOR
! НЕТ
<< сдвиг влево (нулевая заливка справа)
>> сдвиг вправо (распространение знака); копии самого
левого бита (бит знака) сдвигаются слева
>>> сдвиг вправо (нулевая заливка слева). Для положительных чисел
>> и >>> дают одинаковый результат.

Примеры:

x=11 & 6;
console.log(x); // 2

JavaScript поддерживает следующий унарный побитовый оператор :

~ НЕ (инвертирует биты)

Побитовое присвоение

JavaScript поддерживает следующие операторы двоичного присваивания:

знак равно а также
| = или
^ = xor
<< = сдвиг влево (нулевая заливка справа)
>> = сдвиг вправо (распространение знака); копии самого
левого бита (бит знака) сдвигаются слева
>>> = сдвиг вправо (нулевая заливка слева). Для положительных чисел
>> = и >>> = дают одинаковый результат.

Примеры:

x=7;
console.log(x); // 7
x<<=3;
console.log(x); // 7->14->28->56

Нить

знак равно назначение
+ конкатенация
+ = объединить и назначить

Примеры:

str = "ab" + "cd";  // "abcd"
str += "e";      // "abcde"

str2 = "2" + 2;     // "22", not "4" or 4.

??

Ближайшим оператором JavaScript является ??«нулевой оператор объединения», который был добавлен к стандарту в 11-й редакции ECMAScript . В более ранних версиях его можно было использовать через плагин Babel и в TypeScript . Он оценивает свой левый операнд и, если значение результата не является "нулевым" ( nullили undefined), принимает это значение в качестве своего результата; в противном случае он оценивает правый операнд и принимает полученное значение в качестве результата.

В следующем примере aбудет присвоено значение, bесли значение bне равно nullили undefined, в противном случае ему будет присвоено 3.

const a = b ?? 3;

До появления нулевого оператора объединения программисты использовали бы логический оператор ИЛИ ( ||). Но где ??выглядит специально для nullили undefined, то ||оператор выглядит для любого falsy значения: null, undefined, "", 0, NaN, и, конечно же , false.

В следующем примере, aбудет присвоено значение , bесли значение bявляется truthy , в противном случае он будет присвоен 3.

const a = b || 3;

Структуры управления

Составные заявления

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

Если еще

if (expr) {
  //statements;
} else if (expr2) {
  //statements;
} else {
  //statements;
}

Условный (тернарный) оператор

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

 result = condition ? expression : alternative;

такой же как:

 if (condition) {
  result = expression;
 } else {
  result = alternative;
 }

В отличие от оператора if , условный оператор не может опускать «ветвь else».

Заявление о переключении

Синтаксис оператора switch JavaScript следующий:

 switch (expr) {
  case SOMEVALUE:
   // statements;
   break;
  case ANOTHERVALUE:
   // statements;
   break;
  default:
   // statements;
   break;
 }
  • перерыв; необязательно; однако обычно это необходимо, поскольку в противном случае выполнение кода продолжится до тела следующего блока case.
  • Добавьте оператор перерыва в конец последнего случая в качестве меры предосторожности на случай, если позже будут добавлены дополнительные варианты.
  • Значения строкового литерала также могут использоваться для значений case.
  • Вместо значений можно использовать выражения.
  • Случай по умолчанию (необязательный) выполняется, когда выражение не соответствует никаким другим указанным случаям.
  • Подтяжки обязательны.

Для цикла

Синтаксис цикла for в JavaScript следующий:

 for (initial; condition; loop statement) {
  /*
   statements will be executed every time
   the for{} loop cycles, while the
   condition is satisfied
  */
 }

или

 for (initial; condition; loop statement(iteration)) // one statement

For ... in loop

Синтаксис JavaScript for ... in loopследующий:

for (var property_name in some_object) {
  // statements using some_object[property_name];
}
  • Итерирует по всем перечислимым свойствам объекта.
  • Перебирает все используемые индексы массива, включая все определяемые пользователем свойства объекта массива, если таковые имеются. Таким образом, может быть лучше использовать традиционный цикл for с числовым индексом при итерации по массивам.
  • Между различными веб-браузерами существуют различия в том, какие свойства будут отражаться с помощью оператора цикла for ... in. Теоретически это контролируется внутренним свойством состояния, определенным стандартом ECMAscript под названием «DontEnum», но на практике каждый браузер возвращает немного другой набор свойств во время интроспекции. Полезно проверить данное свойство, используя }. Таким образом, добавление метода к прототипу массива с помощью } может вызвать зацикливание имени метода.if (some_object.hasOwnProperty(property_name)) { ...Array.prototype.newMethod = function() {...for ... in

Пока цикл

Синтаксис цикла while в JavaScript следующий:

while (condition) {
  statement1;
  statement2;
  statement3;
  ...
}

Делай ... пока цикл

Синтаксис JavaScript do ... while loopследующий:

do {
  statement1;
  statement2;
  statement3;
  ...
} while (condition);

С участием

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

with (document) {
  var a = getElementById('a');
  var b = getElementById('b');
  var c = getElementById('c');
};
  • Обратите внимание на отсутствие документа. перед каждым вызовом getElementById () .

Семантика аналогична оператору with языка Паскаля .

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

Этикетки

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

loop1: for (var a = 0; a < 10; a++) {
  if (a == 4) {
    break loop1; // Stops after the 4th attempt
  }
  console.log('a = ' + a);
  loop2: for (var b = 0; b < 10; ++b) {
    if (b == 3) {
     continue loop2; // Number 3 is skipped
    }
    if (b == 6) {
     continue loop1; // Continues the first loop, 'finished' is not shown
    }
    console.log('b = ' + b);
  }
  console.log('finished');
}
block1: {
  console.log('Hello'); // Displays 'Hello'
  break block1;
  console.log('World'); // Will never get here
}
goto block1; // Parse error.

Функции

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

function gcd(segmentA, segmentB) {
  var diff = segmentA - segmentB;
  if (diff == 0) 
    return segmentA;
  return diff > 0 ? gcd(segmentB, diff) : gcd(segmentA, -diff);
}
console.log(gcd(60, 40)); // 20

var mygcd = gcd; // mygcd is a reference to the same function as gcd. Note no argument ()s.
console.log(mygcd(60, 40)); // 20

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

Количество аргументов, передаваемых при вызове функции, не обязательно может соответствовать количеству аргументов в определении функции; именованный аргумент в определении, который не имеет соответствующего аргумента в вызове, будет иметь значение undefined (которое может быть неявно преобразовано в false). Внутри функции к аргументам также можно получить доступ через объект arguments ; это обеспечивает доступ ко всем аргументам с использованием индексов (например ), включая те, которые превышают количество именованных аргументов. (Хотя список аргументов имеет свойство .length , он не является экземпляром Array ; у него нет таких методов, как .slice () , .sort () и т. Д.) arguments[0], arguments[1], ... arguments[n]

function add7(x, y) {
  if (!y) {
    y = 7;
  }
  console.log(x + y + arguments.length);
};
add7(3); // 11
add7(3, 4); // 9

Примитивные значения (число, логическое значение, строка) передаются по значению. Для объектов это ссылка на объект, который передается.

var obj1 = {a : 1};
var obj2 = {b : 2};
function foo(p) {
  p = obj2; // Ignores actual parameter
  p.b = arguments[1];
}
foo(obj1, 3); // Does not affect obj1 at all. 3 is additional parameter
console.log(obj1.a + " " + obj2.b); // writes 1 3

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

var v = "Top";
var bar, baz;
function foo() {
  var v = "fud";
  bar = function() { console.log(v) };
  baz = function(x) { v = x; };
}
foo();
baz("Fugly");
bar(); // Fugly (not fud) even though foo() has exited.
console.log(v); // Top

Асинхронный / ожидание

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

Многие библиотеки предоставляют объекты обещаний, которые также можно использовать с ожиданием, если они соответствуют спецификации для встроенных обещаний JavaScript. Однако обещания из библиотеки jQuery не были совместимы с Promises / A + до jQuery 3.0.

Вот пример (измененный из этой статьи):

async function createNewDoc() {
  let response = await db.post({}); // post a new doc
  return await db.get(response.id); // find by id
}

async function main() {
  try {
    let doc = await createNewDoc();
    console.log(doc);
  } catch (err) {
    console.log(err);
  }
}
main();
Node.js версии 8 включает утилиту, которая позволяет использовать методы на основе обратного вызова стандартной библиотеки в качестве обещаний.

Объекты

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

В JavaScript есть несколько видов встроенных объектов, а именно: массив , логическое значение , дата , функция , математика , число , объект , регулярное выражение и строка . Другие объекты - это «хост-объекты», которые определяются не языком, а средой выполнения. Например, в браузере типичные хост-объекты принадлежат DOM (окно, форма, ссылки и т. Д.).

Создание объектов

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

// Constructor
var anObject = new Object();

// Object literal
var objectA = {};
var objectA2 = {};  // A != A2, {}s create new objects as copies.
var objectB = {index1: 'value 1', index2: 'value 2'};

// Custom constructor (see below)

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

var myStructure = {
  name: {
    first: "Mel",
    last: "Smith"
  },
  age: 33,
  hobbies: ["chess", "jogging"]
};

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

Методы

Метод является просто функцией , которая была назначена на имя свойства объекта. В отличие от многих объектно-ориентированных языков, в объектно-ориентированном JavaScript нет различия между определением функции и определением метода. Скорее, различие происходит во время вызова функции; функцию можно вызвать как метод.

При вызове в качестве метода стандартная локальная переменная this просто автоматически присваивается экземпляру объекта слева от " . ". (Также существуют методы вызова и применения, которые могут явно установить это - некоторые пакеты, такие как jQuery, делают с этим необычные вещи .)

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

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

function px() { return this.prefix + "X"; }

function Foo(yz) {
  this.prefix = "a-";
  if (yz > 0) {
    this.pyz = function() { return this.prefix + "Y"; };
  } else {
    this.pyz = function() { return this.prefix + "Z"; };
  }
  this.m1 = px;
  return this;
}

var foo1 = new Foo(1);
var foo2 = new Foo(0);
foo2.prefix = "b-";

console.log("foo1/2 " + foo1.pyz() + foo2.pyz());
// foo1/2 a-Y b-Z

foo1.m3 = px; // Assigns the function itself, not its evaluated result, i.e. not px()
var baz = {"prefix": "c-"};
baz.m4 = px; // No need for a constructor to make an object.

console.log("m1/m3/m4 " + foo1.m1() + foo1.m3() + baz.m4());
// m1/m3/m4 a-X a-X c-X

foo1.m2(); // Throws an exception, because foo1.m2 doesn't exist.

Конструкторы

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

Пример: манипулирование объектом:

function MyObject(attributeA, attributeB) {
  this.attributeA = attributeA;
  this.attributeB = attributeB;
}

MyObject.staticC = "blue"; // On MyObject Function, not object
console.log(MyObject.staticC); // blue

object = new MyObject('red', 1000);

console.log(object.attributeA); // red
console.log(object["attributeB"]); // 1000

console.log(object.staticC); // undefined
object.attributeC = new Date(); // add a new property

delete object.attributeB; // remove a property of object
console.log(object.attributeB); // undefined

delete object; // remove the whole Object (rarely used)
console.log(object.attributeA); // throws an exception

Сам конструктор упоминается в слоте конструктора прототипа объекта . Так,

function Foo() {}
// Use of 'new' sets prototype slots (for example, 
// x = new Foo() would set x's prototype to Foo.prototype,
// and Foo.prototype has a constructor slot pointing back to Foo).
x = new Foo();
// The above is almost equivalent to
y = {};
y.constructor = Foo;
y.constructor();
// Except
x.constructor == y.constructor // true
x instanceof Foo // true
y instanceof Foo // false
// y's prototype is Object.prototype, not
// Foo.prototype, since it was initialised with
// {} instead of new Foo.
// Even though Foo is set to y's constructor slot,
// this is ignored by instanceof - only y's prototype's
// constructor slot is considered.

Функции сами по себе являются объектами, которые можно использовать для создания эффекта, аналогичного «статическим свойствам» (с использованием терминологии C ++ / Java), как показано ниже. (Функциональный объект также имеет специальное свойство прототипа , как описано в разделе «Наследование» ниже.)

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

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

JavaScript поддерживает иерархии наследования посредством прототипирования в манере Self .

В следующем примере класс Derived наследуется от класса Base . Когда d создается как Derived , ссылка на базовый экземпляр Base копируется в d.base .

Derive не содержит значения для aBaseFunction , поэтому он извлекается из aBaseFunction при доступе к aBaseFunction . Это становится понятным путем изменения значения base.aBaseFunction , которое отражается в значении d.aBaseFunction .

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

function Base() {
  this.anOverride = function() { console.log("Base::anOverride()"); };

  this.aBaseFunction = function() { console.log("Base::aBaseFunction()"); };
}

function Derived() {
  this.anOverride = function() { console.log("Derived::anOverride()"); };
}

base = new Base();
Derived.prototype = base; // Must be before new Derived()
Derived.prototype.constructor = Derived; // Required to make `instanceof` work

d = new Derived();    // Copies Derived.prototype to d instance's hidden prototype slot.
d instanceof Derived; // true
d instanceof Base;    // true

base.aBaseFunction = function() { console.log("Base::aNEWBaseFunction()"); }

d.anOverride();    // Derived::anOverride()
d.aBaseFunction(); // Base::aNEWBaseFunction()
console.log(d.aBaseFunction == Derived.prototype.aBaseFunction); // true

console.log(d.__proto__ == base); // true in Mozilla-based implementations and false in many others.

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

function m1() { return "One"; }
function m2() { return "Two"; }
function m3() { return "Three"; }

function Base() {}

Base.prototype.m = m2;
bar = new Base();
console.log("bar.m " + bar.m()); // bar.m Two

function Top() { this.m = m3; }
t = new Top();

foo = new Base();
Base.prototype = t;
// No effect on foo, the *reference* to t is copied.
console.log("foo.m " + foo.m()); // foo.m Two

baz = new Base();
console.log("baz.m " + baz.m()); // baz.m Three

t.m = m1; // Does affect baz, and any other derived classes.
console.log("baz.m1 " + baz.m()); // baz.m1 One

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

Обработка исключений

JavaScript включает оператор try ... catch ... finally обработки исключений для обработки ошибок времени выполнения.

В try ... catch ... finallyзаявлении улавливает исключения , возникающие в результате ошибки или бросок заявления. Его синтаксис следующий:

try {
  // Statements in which exceptions might be thrown
} catch(errorValue) {
  // Statements that execute in the event of an exception
} finally {
  // Statements that execute afterward either way
}

Первоначально выполняются инструкции в блоке try. Если выбрасывается исключение, поток управления сценария немедленно переходит к операторам в блоке catch, при этом исключение доступно в качестве аргумента ошибки. В противном случае блок перехвата пропускается. Блок catch может выбросить (errorValue) , если он не хочет обрабатывать конкретную ошибку.

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

Предложение catch или final можно опустить. Аргумент catch является обязательным.

Реализация Mozilla позволяет использовать несколько операторов catch в качестве расширения стандарта ECMAScript. Они следуют синтаксису, аналогичному используемому в Java :

try { statement; }
catch (e if e == "InvalidNameException")  { statement; }
catch (e if e == "InvalidIdException")    { statement; }
catch (e if e == "InvalidEmailException") { statement; }
catch (e)                                 { statement; }

В браузере событие onerror чаще используется для перехвата исключений.

onerror = function (errorValue, url, lineNr) {...; return true;};

Собственные функции и методы

(Не относится к веб-браузерам.)

eval (выражение)

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

(function foo() {
  var x = 7;
  console.log("val " + eval("x + 2"));
})(); // shows val 9.

Смотрите также

использованная литература

дальнейшее чтение

  • Дэнни Гудман: Библия JavaScript , Wiley, John & Sons, ISBN  0-7645-3342-8 .
  • Дэвид Фланаган, Паула Фергюсон: JavaScript: полное руководство , O'Reilly & Associates, ISBN  0-596-10199-6 .
  • Томас А. Пауэлл, Фриц Шнайдер: JavaScript: полный справочник , McGraw-Hill Companies, ISBN  0-07-219127-9 .
  • Аксель Раушмайер: Разговорный JavaScript: подробное руководство для программистов , 460 страниц, O'Reilly Media, 25 февраля 2014 г., ISBN  978-1449365035 . ( бесплатная онлайн-версия )
  • Эмили Вандер Вир: JavaScript для чайников, 4-е издание , Wiley, ISBN  0-7645-7659-3 .

внешние ссылки