В этом разделе рассказывается немного о JavaScript, чтобы помочь вам понять, почему он такой.
ECMAScript - официальное название JavaScript. Новое название стало необходимо, потому что есть торговая марка на JavaScript (первоначально принадлежащая Sun, теперь Oracle). На данный момент Mozilla является одной из немногих компаний, которым разрешено официально использовать название JavaScript, потому что она получила лицензию давно. Для общего использования применяются следующие правила:
Создатель JavaScript, Брендан Эйх, не имел выбора, кроме как создать язык очень быстро (или другие, худшие технологии были бы приняты Netscape). Он позаимствовал из нескольких языков программирования: Java (синтаксис, примитивные значения против объектов), Scheme и AWK (функции первого класса), Self (прототипное наследие) и Perl и Python (строки, массивы и регулярные выражения).
JavaScript не имел обработки исключений до ECMAScript 3, что объясняет, почему язык так часто автоматически преобразует значения и так часто терпит неудачу: изначально он не мог бросать исключения.
С одной стороны, у JavaScript есть свои нюансы и недостает некоторой функциональности (переменные с объемом блоков, модули, поддержка подклассов и т. Д.). С другой стороны, у него есть несколько мощных функций, которые позволяют обойти эти проблемы.
Учитывая его влияние, неудивительно, что JavaScript обеспечивает стиль программирования, который является смесью функционального программирования (функции высшего порядка; встроенная карта, уменьшить и т. Д.) и объектно-ориентированного программирования (объекты, наследование).
В этом разделе объясняются основные синтаксические принципы JavaScript.
Несколько примеров синтаксиса:
// Two slashes start single-line comments
var x; // declaring a variable
x = 3 + y; // assigning a value to the variable `x`
foo(x, y); // calling function `foo` with parameters `x` and `y`
obj.bar(3); // calling method `bar` of object `obj`
// A conditional statement
if (x === 0) { // Is `x` equal to zero?
x = 123;
}
// Defining function `baz` with parameters `a` and `b`
function baz(a, b) {
return a + b;
}
Обратите внимание на два различных использования знака равенства:
Чтобы понять синтаксис JavaScript, вы должны знать, что он имеет две основные синтаксические категории: заявления и выражения:
var foo;
3 * 7
Различие между инструкциями и выражениями лучше всего проиллюстрировано тем, что JavaScript имеет два различных способа выполнения if-then-else как инструкции:
var x;
if (y >= 0) {
x = y;
} else {
x = -y;
}
или как выражение:
var x = y >= 0 ? y : -y;
Вы можете использовать последний как аргумент функции (но не первый):
myFunction(y >= 0 ? y : -y)
Наконец, там, где JavaScript ожидает заявление, вы также можете использовать выражение; например:
foo(7, 1);
Вся прямая является утверждением (так называемое утверждение выражения), но вызов функции foo ((7, 1) является выражением.
В JavaScript запятые являются необязательными. Тем не менее, я рекомендую всегда включать их, потому что в противном случае JavaScript может ошибочно догадаться о конце заявления. Подробности объясняются в автоматическом вставке запятой.
Полосками заканчиваются заявления, но не блоки. Есть один случай, когда вы увидите полоска после блока: выражение функции - это выражение, которое заканчивается блоком. Если такое выражение приходит последним в заявлении, за ним следует полоска:
// Pattern: var _ = ___;
var x = 3 * 7;
var f = function () { }; // function expr. inside var decl.
JavaScript имеет два вида комментариев: комментарии с одной строкой и комментарии с несколькими строками.
x++; // single-line comment
Комментарии с несколькими строками обозначаются * и *:
/* This is
a multiline
comment.
*/
Переменные в JavaScript декларируются до их использования:
var foo; // declare variable `foo`
Вы можете объявить переменную и назначить значение одновременно:
var foo = 6;
Вы также можете назначить значение существующей переменной:
foo = 4; // change variable `foo`
Существуют операторы сложного назначения, такие как +=. Следующие два назначения эквивалентны:
x += 1;
x = x + 1;
Идентификаторы - это имена, которые играют различные синтаксические роли в JavaScript. Например, имя переменной является идентификатором.
В общем, первым символом идентификатора может быть любая буква Unicode, знак доллара ($) или подчерк (_).
arg0
_tmp
$elem
π
Следующие идентификаторы являются зарезервированными словами, они являются частью синтаксиса и не могут использоваться в качестве имен переменных (включая имена функций и названия параметров):
Следующие три идентификатора не являются зарезервированными словами, но вы должны относиться к ним так, как если бы они были:
Наконец, вы также должны держаться подальше от названий стандартных глобальных переменных. Вы можете использовать их для локальных переменных, ничего не нарушая, но ваш код все равно становится запутанным.
JavaScript имеет множество значений, которые мы ожидаем от языков программирования: булевы, числа, строки, массивы и т. д. Все значения в JavaScript имеют свойства. Каждое свойство имеет ключ (или имя) и значение.
value.propKey
Например, строка
> var str = 'abc';
> str.length
3
Предыдущее также может быть написано так:
> 'abc'.length
3
The dot operator is also used to assign a value to a property:
> var obj = {}; // empty object
> obj.foo = 123; // create property `foo`, set it to 123
123
> obj.foo
123
И вы можете использовать его для вызова методов:
> 'hello'.toUpperCase()
'HELLO'
В предыдущем примере мы вызвали метод toUpperCase() на значении
JavaScript делает несколько произвольное различие между значениями:
> var obj1 = {}; // an empty object
> var obj2 = {}; // another empty object
> obj1 === obj2
false
> obj1 === obj1
true
Напротив, все примитивные значения, кодирующие одно и то же значение, считаются одинаковыми:
> var prim1 = 123;
> var prim2 = 123;
> prim1 === prim2
true
В следующих двух разделах более подробно объясняются примитивные значения и объекты.
Ниже приведены все примитивные значения:
Примитивные имеют следующие характеристики:
> 3 === 3
true
> 'abc' === 'abc'
true
### Всегда неизменный Свойства не могут быть изменены, добавлены или удалены:
> var str = 'abc';
> str.length = 1; // try to change property `length`
> str.length // ⇒ no effect
3
> str.foo = 3; // try to create property `foo`
> str.foo // ⇒ no effect, unknown property
undefined
(Чтение неизвестного свойства всегда возвращает неопределенное.)
Все непримитивные значения являются объектами.
{
firstName: 'Jane',
lastName: 'Doe'
}
Предыдущий объект имеет два свойства: значение свойства firstName -
[ 'apple', 'banana', 'cherry' ]
Предыдущий массив имеет три элемента, к которым можно получить доступ с помощью числовых индексов.
/^a+b+$/
Объекты имеют следующие характеристики:
Идентификации сравниваются; каждое значение имеет свою собственную идентичность:
> ({} === {}) // two different empty objects
false
> var obj1 = {};
> var obj2 = obj1;
> obj1 === obj2
true
Обычно вы можете свободно изменять, добавлять и удалять свойства (см. Единые объекты):
> var obj = {};
> obj.foo = 123; // add property `foo`
> obj.foo
123
Большинство языков программирования имеют значения, обозначающие отсутствующую информацию.
> var foo;
> foo
undefined
Отсутствующие параметры не определены:
> function f(x) { return x }
> f()
undefined
Если вы читаете несуществующее свойство, вы получаете неопределенное:
> var obj = {}; // empty object
> obj.foo
undefined
undefined и null не имеют свойств, даже стандартные методы, такие как toString().
Функции обычно позволяют указывать недостающее значение через undefined или null.
if (x === undefined || x === null) {
...
}
Вы также можете использовать тот факт, что как неопределенные, так и нулевые считаются ложными:
if (!x) {
...
}
false, 0, NaN и
Существует два оператора для классификации значений: typeof используется в основном для примитивных значений, а instanceof используется для объектов. Вид выглядит так:
typeof value
Он возвращает строку, описывающую
> typeof true
'boolean'
> typeof 'abc'
'string'
> typeof {} // empty object literal
'object'
> typeof [] // empty array literal
'object'
В следующей таблице перечислены все результаты типа:
typeof null возвращающий
Пример выглядит так:
value instanceof Constr
Он возвращает true, если значение является объектом, который был создан конструктором Constr (см. Конструкторы: Фабрики для объектов).
> var b = new Bar(); // object created by constructor Bar
> b instanceof Bar
true
> {} instanceof Object
true
> [] instanceof Array
true
> [] instanceof Object // Array is a subconstructor of Object
true
> undefined instanceof Object
false
> null instanceof Object
false
Примитивный булевой тип включает в себя значения true и false.
Всякий раз, когда JavaScript ожидает булевое значение (например, для условия if), можно использовать любое значение. Оно будет интерпретироваться как true или false. Следующие значения интерпретируются как false:
Все остальные значения (включая все объекты!) считаются истинными. Значения, интерпретированные как ложные, называются ложными, а значения, интерпретированные как истинные, называются истинными.
> Boolean(undefined)
false
> Boolean(0)
false
> Boolean(3)
true
> Boolean({}) // empty object
true
> Boolean([]) // empty array
true
Бинарные логические операторы в JavaScript имеют короткое замыкание. То есть, если первого операнда достаточно для определения результата, второй операнд не оценивается. Например, в следующих выражениях функция foo() никогда не называется:
false && foo()
true || foo()
Кроме того, двоичные логические операторы возвращают один из своих операндов, который может быть или не может быть булевым.
Если первый оперант ложный, верните его. В противном случае верните второй оперант:
> NaN && 'abc'
NaN
> 123 && 'abc'
'abc'
Если первый оперант верен, верните его. В противном случае верните второй оперант:
> 'abc' || 123
'abc'
> '' || 123
123
JavaScript имеет два вида равенства:
Нормальное равенство считает (слишком) многими значениями равными (подробности объясняются в Нормальном (Лениентном) Равенстве (==,!=)), что может скрыть ошибки.
Все числа в JavaScript - скользящая запятая:
> 1 === 1.0
true
Специальные номера включают следующие:
NaN (
> Number('xyz') // 'xyz' can’t be converted to a number
NaN
Бесконечность Также в основном значение ошибки:
> 3 / 0
Infinity
> Math.pow(2, 1024) // number too large
Infinity
Бесконечность больше любого другого числа (кроме NaN). Аналогично, - бесконечность меньше любого другого числа (кроме NaN). Это делает эти числа полезными в качестве значения по умолчанию (например, когда вы ищете минимум или максимум).
JavaScript имеет следующие арифметические операторы (см. Арифметические операторы):
Глобальный объект Math (см. Math) обеспечивает больше арифметических операций через функции.
JavaScript также имеет операторы для битовых операций (например, битовые и; см. Битовые операторы).
Строки могут быть созданы непосредственно с помощью литералов строки. Эти литералы определяются одиночными или двойными котировками.
'abc'
"abc"
'Did she say "Hello"?'
"Did she say \"Hello\"?"
'That\'s nice!'
"That's nice!"
'Line 1\nLine 2' // newline
'Backlash: \\'
Доступ к одним символам осуществляется через квадратные скобки:
> var str = 'abc';
> str[1]
'b'
В свойстве length подсчитывается количество символов в строке:
> 'abc'.length
3
Как и все примитивы, строки неизменны; вам нужно создать новую строку, если вы хотите изменить существующую.
Строки соединены через оператор плюс (+), который преобразует другой оперант в строку, если один из операндов является строкой:
> var messageCount = 3;
> 'You have ' + messageCount + ' messages'
'You have 3 messages'
Чтобы соединить строки в несколько шагов, используйте оператор +=:
> var str = '';
> str += 'Multiple ';
> str += 'pieces ';
> str += 'are concatenated.';
> str
'Multiple pieces are concatenated.'
У струн есть много полезных методов (см. Методы прототипов струн). Вот несколько примеров:
> 'abc'.slice(1) // copy a substring
'bc'
> 'abc'.slice(1, 2)
'b'
> '\t xyz '.trim() // trim whitespace
'xyz'
> 'mjölnir'.toUpperCase()
'MJÖLNIR'
> 'abc'.indexOf('b') // find a string
1
> 'abc'.indexOf('x')
-1
Условия и петли в JavaScript представлены в следующих разделах.
Указание if имеет then-заголовок и дополнительный else-заголовок, которые выполняются в зависимости от булевого условия:
if (myvar === 0) {
// then
}
if (myvar === 0) {
// then
} else {
// else
}
if (myvar === 0) {
// then
} else if (myvar === 1) {
// else-if
} else if (myvar === 2) {
// else-if
} else {
// else
}
Я рекомендую всегда использовать скобки (они обозначают блоки с нулем или более заявлений). Но вам не нужно делать это, если пункт представляет собой только одно заявление (то же самое относится к заявлениям потока управления для и в то время как):
if (x < 0) return -x;
Следующее указание - значение фрукта, которое определяет, какой случай выполняется:
switch (fruit) {
case 'banana':
// ...
break;
case 'apple':
// ...
break;
default: // all other cases
// ...
}
Ключа for имеет следующий формат:
for (⟦«init»⟧; ⟦«condition»⟧; ⟦«post_iteration»⟧)
«statement»
init выполняется в начале цикла. condition проверяется перед каждой итерацией цикла; если он становится ложным, то цикл заканчивается. post_iteration выполняется после каждой итерации цикла.
Этот пример распечатывает все элементы массива arr на консоли:
for (var i=0; i < arr.length; i++) {
console.log(arr[i]);
}
Период цикла продолжает циркулировать над его телом, пока его состояние сохраняется:
// Same as for loop above:
var i = 0;
while (i < arr.length) {
console.log(arr[i]);
i++;
}
Поскольку состояние следует за телом, тело всегда выполняется по крайней мере один раз:
do {
// ...
} while (condition);
Во всех циклах:
Один из способов определения функции - через декларацию функции:
function add(param1, param2) {
return param1 + param2;
}
Предыдущий код определяет функцию, которая имеет два параметра, param1 и param2, и возвращает сумму обоих параметров.
> add(6, 1)
7
> add('a', 'b')
'ab'
Другой способ определения add (() - это присвоение функционного выражения переменной add:
var add = function (param1, param2) {
return param1 + param2;
};
Функционное выражение производит значение и, таким образом, может быть использовано для прямого передачи функций в качестве аргументов другим функциям:
someOtherFunction(function (p1, p2) { ... });
Декларации функций поднимаются
function foo() {
bar(); // OK, bar is hoisted
function bar() {
...
}
}
Обратите внимание, что в то время как декларации var также поднимаются (см. Переменные поднимаются), задания, выполняемые ими, не являются:
function foo() {
bar(); // Not OK, bar is still undefined
var bar = function () {
// ...
};
}
Вы можете вызвать любую функцию в JavaScript с произвольным количеством аргументов; язык никогда не будет жаловаться. Тем не менее, он сделает все параметры доступными через специальные переменные аргументы. аргументы выглядят как массив, но не имеет ни одного из методов массива:
> function f() { return arguments }
> var args = f('a', 'b', 'c');
> args.length
3
> args[0] // read element at index 0
'a'
Давайте используем следующую функцию, чтобы исследовать, как слишком много или слишком мало параметров обрабатываются в JavaScript (функция toArray( показана в Конвертирование аргументов в массив):
function f(x, y) {
console.log(x, y);
return toArray(arguments);
}
Дополнительные параметры игнорируются (кроме аргументов):
> f('a', 'b', 'c')
a b
[ 'a', 'b', 'c' ]
Отсутствие параметров приведет к неопределенному значению:
> f('a')
a undefined
[ 'a' ]
> f()
undefined undefined
[]
Ниже приведена общая схема присвоения параметрам значения по умолчанию:
function pair(x, y) {
x = x || 0; // (1)
y = y || 0;
return [ x, y ];
}
В строке (1), оператор "вывести" возвращает x, если он является истинным (не нулевым, неопределенным и т. д.). В противном случае он возвращает второй оперант:
> pair()
[ 0, 0 ]
> pair(3)
[ 3, 0 ]
> pair(3, 5)
[ 3, 5 ]
Если вы хотите ввести arity (определенное количество параметров), вы можете проверить arguments.length:
function pair(x, y) {
if (arguments.length !== 2) {
throw new Error('Need exactly 2 arguments');
}
...
}
arguments - это не массив, это только массивный (см. Array-Like Objects and Generic Methods). Он имеет длину свойства, и вы можете получить доступ к его элементам через индексы в квадратных скобках. Вы, однако, не можете удалять элементы или вызывать какие-либо из методов массива на нем. Таким образом, иногда вам нужно конвертировать аргументы в массив, что делает следующая функция (это объясняется в Array-Like Objects and Generic Methods):
function toArray(arrayLikeObject) {
return Array.prototype.slice.call(arrayLikeObject);
}
Наиболее распространенным способом обращения с исключениями (см. главу 14) является следующее:
function getPerson(id) {
if (id < 0) {
throw new Error('ID must not be negative: '+id);
}
return { id: id }; // normally: retrieved from database
}
function getPersons(ids) {
var result = [];
ids.forEach(function (id) {
try {
var person = getPerson(id);
result.push(person);
} catch (exception) {
console.log(exception);
}
});
return result;
}
Клауза try окружает критический код, а клауза catch выполняется, если исключение бросается внутри клаузы try.
> getPersons([2, -5, 137])
[Error: ID must not be negative: -5]
[ { id: 2 }, { id: 137 } ]
Строгий режим (см. Строгий режим) позволяет больше предупреждений и делает JavaScript более чистым языком (нестрогий режим иногда называют
'use strict';
Вы также можете включить строгий режим на функцию:
function functionInStrictMode() {
'use strict';
}
В JavaScript вы объявляете переменные через var перед их использованием:
> var x;
> x
undefined
> y
ReferenceError: y is not defined
Вы можете объявить и инициировать несколько переменных с помощью одного заявления var:
var x = 1, y = 2, z = 3;
Но я рекомендую использовать одно утверждение на переменную (причина объясняется в синтаксисе). Таким образом, я перепишу предыдущее утверждение на:
var x = 1;
var y = 2;
var z = 3;
Из-за подъема (см. Переменные поднимаются), обычно лучше всего объявлять переменные в начале функции.
Объем переменной всегда является полной функцией (в отличие от текущего блока).
function foo() {
var x = -512;
if (x < 0) { // (1)
var tmp = -x;
...
}
console.log(tmp); // 512
}
Мы видим, что переменная tmp не ограничивается блоком, начинающимся в строке (1); она существует до конца функции.
Каждая декларация переменной поднимается: декларация переносится в начало функции, но задания, которые она делает, остаются.
function foo() {
console.log(tmp); // undefined
if (false) {
var tmp = 3; // (1)
}
}
Внутренне предыдущая функция выполняется следующим образом:
function foo() {
var tmp; // hoisted declaration
console.log(tmp);
if (false) {
tmp = 3; // assignment stays put
}
}
Каждая функция остается связанной с переменными окружающих ее функций, даже после того, как она покидает область, в которой она была создана.
function createIncrementor(start) {
return function () { // (1)
start++;
return start;
}
}
Функция, начинающаяся в строке (1), выходит из контекста, в котором она была создана, но остается подключенной к живой версии старта:
> var inc = createIncrementor(5);
> inc()
6
> inc()
7
> inc()
8
Закрытие представляет собой функцию плюс соединение с переменными ее окружающих областей. Таким образом, то, что возвращает createIncrementor(), является закрытием.
Иногда вы хотите ввести новую область действия переменной, например, чтобы предотвратить глобализацию переменной. В JavaScript вы не можете использовать блок для этого; вы должны использовать функцию. Но есть шаблон для использования функции в блоковом виде. Он называется IIFE (немедленно вызванное выражение функции, произносится
(function () { // open IIFE
var tmp = ...; // not a global variable
}()); // close IIFE
Убедитесь, что вы ввели предыдущий пример точно так же, как показано (за исключением комментариев). IIFE - это выражение функции, которое вызывается сразу после его определения. Внутри функции существует новый объем, что предотвращает глобализацию tmp.
Закрытия сохраняют свои связи с внешними переменными, что иногда не то, что вы хотите:
var result = [];
for (var i=0; i < 5; i++) {
result.push(function () { return i }); // (1)
}
console.log(result[1]()); // 5 (not 1)
console.log(result[3]()); // 5 (not 3)
Значение, возвращаемое в строке (1), всегда является текущим значением i, а не значением, которое оно имело при создании функции. После завершения цикла i имеет значение 5, поэтому все функции в массиве возвращают это значение. Если вы хотите, чтобы функция в строке (1) получила снимок текущего значения i, вы можете использовать IIFE:
for (var i=0; i < 5; i++) {
(function () {
var i2 = i; // copy current i
result.push(function () { return i2 });
}());
}
В этом разделе рассматриваются два основных объектно-ориентированных механизма JavaScript: одиночные объекты и конструкторы (которые являются фабриками для объектов, аналогичны классам в других языках).
Как и все значения, объекты имеют свойства. Вы можете, на самом деле, рассматривать объект как набор свойств, где каждое свойство является парой (ключ, значение). Ключ является строкой, а значение - любое значение JavaScript.
В JavaScript, вы можете создавать простые объекты прямо, через объекты буквальных:
'use strict';
var jane = {
name: 'Jane',
describe: function () {
return 'Person named '+this.name;
}
};
Предыдущий объект имеет свойства name и describe. Вы можете читать (
> jane.name // get
'Jane'
> jane.name = 'John'; // set
> jane.newProperty = 'abc'; // property created automatically
Свойства с значениями функций, такие как describe, называются методами.
> jane.describe() // call method
'Person named John'
> jane.name = 'Jane';
> jane.describe()
'Person named Jane'
Оператор in проверяет наличие свойства:
> 'newProperty' in jane
true
> 'foo' in jane
false
Если вы читаете свойство, которое не существует, вы получаете значение undefined.
> jane.newProperty !== undefined
true
> jane.foo !== undefined
false
Оператор " Удалить " удаляет свойство:
> delete jane.newProperty
true
> 'newProperty' in jane
false
Ключ свойства может быть любой строкой. До сих пор мы видели ключи свойства в объектах буквальных и после точечного оператора. Однако вы можете использовать их таким образом только если они являются идентификаторами (см. Идентификаторы и имена переменных). Если вы хотите использовать другие строки в качестве ключей, вы должны процитировать их в объекте буквальном и использовать квадратные скобки, чтобы получить и установить свойство:
> var obj = { 'not an identifier': 123 };
> obj['not an identifier']
123
> obj['not an identifier'] = 456;
Квадратные скобки также позволяют вычислить ключ свойства:
> var obj = { hello: 'world' };
> var x = 'hello';
> obj[x]
'world'
> obj['hel'+'lo']
'world'
Если вы извлекаете метод, он теряет связь с объектом. сам по себе функция больше не является методом, и это имеет значение undefined (в строгом режиме).
В качестве примера, давайте вернемся к предыдущему объекту Jane:
'use strict';
var jane = {
name: 'Jane',
describe: function () {
return 'Person named '+this.name;
}
};
Мы хотим извлечь метод describe из jane, поместить его в переменную func, и вызвать его.
> var func = jane.describe;
> func()
TypeError: Cannot read property 'name' of undefined
Решение состоит в том, чтобы использовать метод bind(), который есть у всех функций. Он создает новую функцию, которая всегда имеет данное значение:
> var func2 = jane.describe.bind(jane);
> func2()
'Person named Jane'
Каждая функция имеет свою специальную переменную this. Это неудобно, если вы встраиваете функцию внутри метода, потому что вы не можете получить доступ к методу this из функции. Ниже приведен пример, где мы называем forEach с функцией для итерации над массивом:
var jane = {
name: 'Jane',
friends: [ 'Tarzan', 'Cheeta' ],
logHiToFriends: function () {
'use strict';
this.friends.forEach(function (friend) {
// `this` is undefined here
console.log(this.name+' says hi to '+friend);
});
}
}
Призыв logHiToFriends приводит к ошибке:
> jane.logHiToFriends()
TypeError: Cannot read property 'name' of undefined
Во-первых, мы можем хранить это в другой переменной:
logHiToFriends: function () {
'use strict';
var that = this;
this.friends.forEach(function (friend) {
console.log(that.name+' says hi to '+friend);
});
}
Или, forEach имеет второй параметр, который позволяет предоставить значение для этого:
logHiToFriends: function () {
'use strict';
this.friends.forEach(function (friend) {
console.log(this.name+' says hi to '+friend);
}, this);
}
Функционные выражения часто используются в качестве аргументов в вызовах функций в JavaScript.
До сих пор вы могли думать, что объекты JavaScript - это только карты от строк до значений, понятие, предложенное объектами JavaScript
В дополнение к тому, что функции являются
// Set up instance data
function Point(x, y) {
this.x = x;
this.y = y;
}
// Methods
Point.prototype.dist = function () {
return Math.sqrt(this.x*this.x + this.y*this.y);
};
Мы видим, что конструктор имеет две части. Во-первых, функция Point устанавливает данные экземпляров. Во-вторых, свойство Point.prototype содержит объект с методами. Первые данные специфичны для каждого экземпляра, в то время как последние данные обмениваются между всеми экземплярами.
Чтобы использовать Point, мы вызываем его через новый оператор:
> var p = new Point(3, 5);
> p.x
3
> p.dist()
5.830951894845301
p представляет собой экземпляр Point:
> p instanceof Point
true
Массивы - это последовательности элементов, к которым можно получить доступ через целые индексы, начиная с нуля.
Литералы массивов полезны для создания массивов:
> var arr = [ 'a', 'b', 'c' ];
Предыдущий массив имеет три элемента: строки
> arr[0]
'a'
> arr[0] = 'x';
> arr
[ 'x', 'b', 'c' ]
С помощью свойства length можно добавлять элементы и удалять элементы:
> var arr = ['a', 'b'];
> arr.length
2
> arr[arr.length] = 'c';
> arr
[ 'a', 'b', 'c' ]
> arr.length
3
> arr.length = 1;
> arr
[ 'a' ]
Оператор in работает и для массивов:
> var arr = [ 'a', 'b', 'c' ];
> 1 in arr // is there an element at index 1?
true
> 5 in arr // is there an element at index 5?
false
Обратите внимание, что массивы являются объектами и, следовательно, могут иметь свойства объектов:
> var arr = [];
> arr.foo = 123;
> arr.foo
123
У массивов много методов (см. Методы прототипов массивов). Вот несколько примеров:
> var arr = [ 'a', 'b', 'c' ];
> arr.slice(1, 2) // copy elements
[ 'b' ]
> arr.slice(1)
[ 'b', 'c' ]
> arr.push('x') // append an element
4
> arr
[ 'a', 'b', 'c', 'x' ]
> arr.pop() // remove last element
'x'
> arr
[ 'a', 'b', 'c' ]
> arr.shift() // remove first element
'a'
> arr
[ 'b', 'c' ]
> arr.unshift('x') // prepend an element
3
> arr
[ 'x', 'b', 'c' ]
> arr.indexOf('b') // find the index of an element
1
> arr.indexOf('y')
-1
> arr.join('-') // all elements in a single string
'x-b-c'
> arr.join('')
'xbc'
> arr.join()
'x,b,c'
Существует несколько методов массива для итерации элементов (см. Итерация (неразрушительная)).
forEach повторяется над массивом и передает текущий элемент и его индекс функции:
[ 'a', 'b', 'c' ].forEach(
function (elem, index) { // (1)
console.log(index + '. ' + elem);
});
Предыдущий код дает следующий результат:
0. a
1. b
2. c
Обратите внимание, что функция в строке (1) может игнорировать аргументы.
map создает новый массив, применяя функцию к каждому элементу существующего массива:
> [1,2,3].map(function (x) { return x*x })
[ 1, 4, 9 ]
JavaScript имеет встроенную поддержку регулярных выражений.
/^abc$/
/[A-Za-z0-9]+/
> /^a+b+$/.test('aaab')
true
> /^a+b+$/.test('aaa')
false
> /a(b+)a/.exec('_abbba_aba_')
[ 'abbba', 'bbb' ]
Возвращенный массив содержит полное совпадение в индексе 0, захват первой группы в индексе 1 и так далее.
> '<a> <bbb>'.replace(/<(.*?)>/g, '[$1]')
'[a] [bbb]'
Первый параметр replace должен быть регулярным выражением с флагом /g; в противном случае, заменяется только первое occurrence.
Математика - это объект с арифметическими функциями. Вот несколько примеров:
> Math.abs(-2)
2
> Math.pow(3, 2) // 3 to the power of 2
9
> Math.max(2, -1, 5)
5
> Math.round(1.9)
2
> Math.PI // pre-defined constant for π
3.141592653589793
> Math.cos(Math.PI) // compute the cosine for 180°
-1