Statements

  • statement; - инструкция
  • ;;; - пустые инструкции
  • console.log("Hello"); - вывод в консоль
  • // текст комментария
  • Индексы (указатели на место) нумеруются с нуля

Variables

  • var num; - декларация (объявление) переменной
  • num = 342 + 324; - вычисление значения выражения и присвоение результата в переменную
  • декларацию и присвоение можно производить одновременно и для множества переменных: var myVar1=20, myVar2 = 30;
  • названия переменных регистрозависимы и не могут начинаться с цифры: var variable, _variable, $var;
  • имеется список запрещенных для переменных имен, но все они используются в самом языке либо как названия функций, значений и прочего: break, delete, case, do, catch, else, continue, false и так далее
  • при попытке что-либо сделать с переменной до её декларации и присвоения значения - ошибки не будет, и значение у переменной будет undefined. Это связано с тем, что инструкция var num = 5; делится на две части: 1) var num; 2) num = 5; и первая часть поднимается в самый верх кода. Эта особенность называется Hoisting. Если более конкретно, то Hoisting это поднятие вверх всех var без присвоения значения (присвоения остаются на прежних местах)

Data Types

  • num = 25; - число (Number)
  • str = "hello"; - строка (String)
  • boo = true; - логическое значение (Boolean)
  • nu = null; - отсутствующее значение
  • und = undefined; - неопределенное значение
  • obj = {name: "John"}; - объект
  • arr = [1, 2, 3]; - массив
  • regexp = /w+/g; - регулярное выражение
  • func = function(){}; - функция
  • первые 4 переменных заданы литералами, пятая - идентификатором
  • литералы - возможные значения определенного типа данных:
    • 543543 - литерал числа
    • "Hello" - литерал строки
    • false - логический литерал
    • null - литерал null
    • {name: "John"} - литерал объекта
  • тип переменной зависит от её текущего значения и меняется исходя из её значения, то есть является непостоянным
  • typeof num; или typeof(num); - выводит тип значения переменной в виде текста
  • typeof(null); - выдаст object - это ошибка языка и она никогда не будет исправлена
  • на самом деле, всё в JS является объектом
  • таким образом всё является всем, то есть из одного типа можно использовать методы другого типа, но не всегда
  • методы - это функции объекта, но так как всё в языке является объектом, то и методы можно использовать практически у любых типов данных: "s".toUpperCase();
  • методы и функции редко меняют значение самой переменной, чаще всего они возвращают в место своего вызова результат своих преобразований над значением переменной (очень утрированно)
  • obj.name = "Harry"; - меняет значение параметра name объекта obj
  • arr[1] = 325; - меняет элемент массива с индексом 1, то есть второй
  • a = b = c = d = 5; - читается слева направо, но исполняется справа налево

Numbers

  • Все вещественные числа от -2^53 до 2^53
  • Десятичные пишутся как есть
  • Шестнадцатиричные - 0xfffcc
  • Восьмиричные - 0345
  • 12.45
  • .89
  • 1.34e4 = 13400
  • 1.34e-10
  • var n = new Number(4000); - создание числа через конструктор (подобно объекту)
  • n.toFixed(2); - всегда 2 знака после запятой (фиксирует точку)
  • чтобы использовать методы у литерала нужно дописать пробел: 2 .toFixed(2);
  • 2 .toExponential(2); - 2.00e+0
  • 2 .toPrecision(8); - выведет всего 8 знаков от числа (с точностью 8 знаков, захватывая целую часть)
  • i = 10;
    • -i; // i = -10 - меняет знак на отрицательный
    • +i; // i = 10 - меняет знак на положительный
    • ++i; i++; // i = 11 // i = 12 - инкремент, увеличивают значение на единицу
      • ++i; - увеличивает, затем возвращает значение
      • i++; - возвращает значение, затем увеличивает
    • --i; i--; - декремент
  • 5 + 10;
  • 7 - 3;
  • 5 * 9;
  • 10 / 3; - нецелочисленное деление
  • 10 % 3; - остаток от деления
  • n += 20; - аналогично n = n + 20;
  • Аналогично n -= 20; n *= 20; n /= 20;
  • 5 > 10 // false
  • 5 < 10 // true
  • 10 >= 10 // true
  • 8 <= 10 // false
  • 10 === 10 // true - сравнение без приведения типов
  • 10 !== 10 // false
  • 10 == "10" // true - сравнение с приведением типов
  • 10 === "10" // false
  • Math.sqrt(25); - квадратный корень из числа 25
  • Math.pow(3, 5); - число 3 в степени 5
  • Math.PI; Math.E; - математические константы
  • При выходе за диапазон очень большое число (по модулю) будет записано как Infinity (тип Number); очень маленькое (приближается к нулю) будет записано как 0
  • Может быть -Infinity
  • 5 / 0; // = Infinity
  • 0 / 0; // = NaN (Not a Number) (тип Number, как не парадоксально)
  • Infinity / Infinity; // = NaN
  • Math.sqrt(-10); // = NaN
  • Проверка NaN на равенство (даже с NaN) всегда возвращает false
  • 0,2 + 0,1 // = 0,30000000000004, случаются ошибки округления

Strings

  • "string", 'string' - неважно какие кавычки
  • Разные кавычки используются для кавычек внутри кавычек: "bla bla bla 'name' bla bla bla";
  • string.length - длина в символах
  • Специальные символы:
    • \ в конце строки - перенос строки (нельзя не в конце строки)
    • \n - перевод на новую строку
    • \t - табуляция
    • \" - экранированные кавычки, можно использовать внутри таких же кавычек
    • \\ - экранированный \
  • "Hello " + "world"; // = "Hello world"
  • string.charAt(0); - вернет символ на месте с индексом 0
  • string.substring(10, 21); - вернет строку с 11 элемента по 22 элемент
    • Также можно указывать только 1 число в скобках, тогда строка будет взята от этого символа и до конца
  • string.slice(-10); - убирает символы с начала строки (отрицательное число - с конца)
  • string.substr(14, 4); - аналогично substring, но указываем начальный символ и количество символов соответственно
  • string.indexOf("i"); - вернет индекс первого найденного i
  • string.lastIndexOf("i"); - аналогично indexOf, но с конца
  • string.replace("is", "is not"); - ищет первое встреченное "is" и заменяет на "is not", возвращает результат, но не меняет исходную переменную
  • string.split(","); - разбивает строку на массив по разделителю ,
  • string.toUpperCase(); - все буквы становятся прописными, не меняя исходную переменную
  • string.toLowerCase(); - все буквы становятся строчными
  • К строчным переменным можно обращаться как к массиву, как будто строка это массив строк по 1 символу: string[4];

Booleans

  • new Boolean(5); // true
  • undefined, null, 0, NaN и "" при преобразовании к логическому типу вернут false ("" - пустая строка)
  • Все остальные варианты вернут true
  • true && true; - логическое "и"
  • true || true; - логическое "или"
  • !true; // false - логическое отрицание
  • Логические операторы заставляют код работать немного иначе, так как они оптимизируют свои действия
  • Так как логическое "и" требует, чтобы обе переменные были true, то сначала проверяется равна ли первая переменная true. Если это так, только тогда проверяется вторая. Если же первая переменная (или выражение) равна false, то вторая переменная даже не будет вычисляться (в случае выражения)
  • При этом если результат сравнения заносится в какую-либо переменную, то там будет не true или false, а значение (необязательно логическое) последнего высчитанного выражения: bool = "2" && 1; // bool = 1
  • Допустим, что значение переменной someString нам неизвестно. Но оно может быть, а может и не быть. В таком случае, чтобы избежать неопределенностей можно написать такой код: var newString = someString || "Default String"; Таким образом если у someString есть значение, то именно оно запишется в newString, так как логическое "или" требует хотя бы одного true и не будет высчитываться дальше. Если же someString, например, равен undefined, то в newString будет записано "Default String"

Null, Undefined

  • null - пустое значение
  • undefined - неопределенное значение; переменная без значения; несуществующий элемент массива; несуществующее поле объекта; если функции не передали значение, но нужно было; если функция ничего не возвращает через return, то вернет undefined
  • null == undefined; // true
  • null === undefined; // false

Types Conversion

  • Преобразование типов (в том числе, и во время сравнения значений переменных) не всегда проходит логично. Поэтому рекомендуется все преобразования делать явным образом
  • 5 + "5"; // "55" - при сложении строки и числа, они приводятся к строке; при вычитании - приводятся к числу, что может привести к результату в виде NaN (например, строку "5px" нельзя привести к числу и получится NaN)
  • "5" * "4"; // 20 - умножение проводится с числами
  • "5" * "hi"; // NaN - по крайней мере, пытается
  • "5" == 5; // true
  • "0" == false; // true
  • 0 == false; // true - последние три вполне логично, а вот дальше...
  • "5" == true; // false - потому что вместо преобразования "5" к логическому типу, true преобразуется к строчному
  • "" == false; // true
  • null == false; // false
  • null == true; // false
  • undefined == false; // false
  • undefined == true; // false
  • undefined == null; // true
  • Number("555"); // 555
  • String(4433); // "4433"
  • Boolean(1); // true
  • !! - двойное отрицание, иначе говоря два последовательных отрицания. Оно отрицает значение переменной, при этом преобразуя её к логическому типу. Их может быть хоть миллион подряд, только зачем
  • !!5; // true
  • !!0; // false
  • 345 + ""; // "345"
  • +"345"; // 345
  • number.toString(2); - преобразует число в строку с указанием желаемой системы исчисления (в данном примере, двоичная). Можно не указывать, тогда будет десятичная
  • false.toString(); // "false" - работает не только с числами
  • parseInt("45 px", 10); - переводит в целое число в системе исчисления 10
  • parseFloat("12.34 em"); - в вещественное число
  • String(Infinity); - в строку
  • +""; // 0
  • +       "4"; // 4
  • +"  g   4"; // NaN
  • +true; // 1
  • +false; // 0
  • null и undefined не могут быть преобразованы объектной оберткой в объект
  • !!""; // false
  • !!NaN; // false
  • !!0; // false
  • !!null; // false
  • !!undefined; // false
  • !!"Hi"; // true

Conditions

Conditional Statements

  • Если инструкция простая:

    	if(true) console.log("It's true");
    
  • Если по-сложнее:

    	if(n > 3) {
    		n *= 3;
    		console.log(n);
    	} else {
    		...
    	};
    
  • В if проверяется условие. Если оно true, то выполняются инструкции в первых {}, если нет, то в {} после else

  • Также доступна форма с множественными условиями и вариантами:

    	if() {
    		...
    	} else if() {
    		...
    	} else {
    		...
    	};
    
  • Switch

    	switch(выражение) {
    		case значение1: инструкции;
    		case значение2: инструкции;
    		default: инструкции;
    	}
    

    Когда выражение принимает значение1, то выполняются все инструкции начиная с case значение1 и до конца switch. Если выражение имеет другое неравное никаким значениям значение, то выполняется только default

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

Conditional Operator

  • var next = x>10 ? "bla1" : "bla2"; - выражение перед ? является условием (аналогично if), выражение после ? является инструкциями в случае если условие принимает значение true, выражение после : - инструкции для false
  • Более сложная форма, аналогичная if {} else if {} else: x>10 ? "bla1" : x<10 ? "bla2" : "bla3";

Period

  • var test = (15, 20); - вычисляются оба значения, но возвращается последнее (20)

Loops

  • for(var i=0; i<10; i++) { ... } - цикл с указание счетчика и его начального значения, условия выполнения цикла и функции изменения счетчика. Сначала проверяется соответствие условию и затем выполняется итерация цикла
  • while(i<10) { ... } - цикл с условием, но без счетчика. Условие проверяется перед выполнением итерации
  • do { ... } while(i<10) - аналог while, но условие проверяется после итерации

Functions

  • function name(argument) { return "bla"; }; - объявление (декларация) функции. Это лишь описание функция. Декларация не исполняет функцию
  • argument - имя переменной внутри функции, в которую будет записано передаваемое в функцию значение
  • return; - что вернет функция после выполнения
  • name("arg"); - вызов функции
  • "arg" - значение, передаваемое в функцию
  • Так как функция возвращает значение в место своего вызова, то с ним можно работать как с обычными данными соответствующих типов. Например, наша функция возвращает строку, значит мы можем написать следующее: name().toUpperCase();
  • Выше указано задание функции через её название. Также можно записать анонимную функцию в переменную. Внешней разницы никакой нет: var name = function(argument) { ... }; Вызываться эта функция будет точно также как и в примере выше
  • Так как всё в JS выполняется почти одновременно (но это не точно), то для того, чтобы был четки порядок выполнения, можно использовать callback. Так называют функции, вызываемые внутри других функций. Таким образом callback начинает выполнение строго после начала выполнения самой функции
  • В функцию можно передавать абсолютно любые типы данных, в том числе и другие функции. Это же справедливо и для возвращаемых из функции данных
  • Уровень вложенности бесконечен
  • Декларация анонимных функций не имеет смысла, если к ним никак нельзя обратиться
  • Анонимной самовызывающейся функцией называют функцию, которая возвращает результат своего выполнения в момент декларации, например:
    	var greetings = (function(name) {
    		return "Hello " + name;
    	}("John"));
    
    Вызов этой функции идет сразу же при декларации и теперь переменная greetings содержит результат выполнения функции, а не саму функцию

Scopes

  • Существует два вида переменных: глобальные и локальные. Глобальные переменные хранятся на глобальном объекте и видны на всей области видимости, то есть во всей программе. Локальные видны лишь внутри соответствующих областей. Например, у нас есть глобальная переменная count. Внутри какой-нибудь функции мы может обращаться и изменять эту переменную по её имени. Но если мы напишем внутри функции var count; то это означает, что мы создаем переменную с таким же именем, как и у глобальной переменной, но уже не имеем к ней доступа и не влияем на неё. Если же внутри этой функции создать ещё одну функцию, то всё будет работать точно также

Closures

  • К переменным, созданным внутри функций, никак извне нельзя получить доступ. Однако функции внутри функций могут их менять, так как внутренние переменные для них считаются глобальными. То есть это защищает данные внутри функции от влияния извне, если вы этого не хотите
    	var counter = (function() {
    		var count = 0;
    		return function(num){
    			count = num !== undefined ? num : count;
    			return count++;
    		};
    	}());
    	console.log(counter()); // 0
    	console.log(counter()); // 1
    	console.log(counter()); // 2
    

Exceptions

  • Чтобы создать исключение, которое прерывает выполнение функции или всей программы, нужно написать throw "Hello";
  • Можно выкидывать исключения более сложного формата в виде объекта Error
  • var myError = new Error("My Error Message");
  • У объекта Error есть поля name и message, обращение к ним стандартно как у объектов
  • throw myError;
  • Также можно создавать объекты типа SyntaxError и ReferenceError, которые логически соответствуют своим названиям, но не имеют принципиальных различий
  • Для того, чтобы поймать исключение и что-то с этим сделать, нужно использовать особую конструкцию
  • Пример:
    	try {
    		инструкции, которые могут выбросить исключение
    	} catch {
    		инструкции, которые будут выполнены в случае наличия исключения
    	} finally {
    		инструкции, которые будут выполнены независимо от наличия исключений
    	}
    
  • Либо catch, либо finally могут отсутствовать, но не одновременно

Objects

  • Пример
    	var person = {
    		name: "John",
    		age: 20,
    		gender: "male",
    		sayHi: function(){
    			return "Hello";
    		}
    	}
    
  • Поля объекта имеют 2 составляющие: имя, по которому можно к нему обратиться, и значение
  • Значение поля объекта может быть чем-угодно, в том числе и другим объектом
  • Метод - функция внутри объекта
  • Уровень вложенности также бесконечен
  • person.name; - обращение к полю объекта
  • Также к полю можно обратится как к элементу массива: person["name"];
  • Если обратится к полю, которого нет в объекте, то вернется undefined
  • person.age = 25; - изменение значения поля объекта
  • Через изменение несуществующего поля, можно создать его: person.id = 2234;
  • var obj = new Object(); - создание объекта
  • var obj = Object.create(null); - тоже создание объекта, но на основе прототипа (конкретно здесь, null)
  • var obj = Object.create({x: 10, y: 20}); - создание через прототип позволит наследовать поля, их значения, но иметь он их не будет. При попытке изменить их или создать такие же, будут созданы собственные поля с такими же названиями
  • Можно удалить собственное (но не наследованное) поле: delete obj.name;
  • Можно проверить наличие поля в объекте разными способами
    • "x" in obj; - всё равно, свои или наследованные
    • object.hasOwnProperty("x"); - только свои
  • Рассмотрим пример: var a=10, b=20; a=b; b=15;
  • Здесь мы меняем значение a на значение b, и дальнейшее изменение b никак не влияет на a
  • Рассмотрим другой пример: var a={x:10}, b={x:20}; a=b; b.x=15; a.x=45;
  • Здесь строчкой a=b мы переписали ссылки на объект, теперь и a, и b ссылаются на одну и ту же область памяти, то есть на один и тот же объект. Поэтому неважно по какому имени мы будем обращаться к нему

This

  • По-умолчанию, указывает на область видимости на один уровень выше вызова this
  • person.sayHi.call(person); - вызывает функцию, которая хранится в поле sayHi объекта person, но this будет указывать на то, что указано в скобках (здесь - на person)
  • Также мы можем передать при таком вызове функции входные параметры для неё: person.sayHi.call(person, "Hi");
  • Аналогично можно вызвать эту функцию, но передавая ей входные параметры не через запятую, а массивом: person.sayHi.apply(person, ["Hi"]);
  • Также можно создать новую функцию, в которой будет изменено значение this на указанное, но её вызов будет выглядеть проще, без вызовов call и apply: var bound = person.sayHi.bind(person); Вызов будет выглядеть так: bound("Hi");

Accessors

  • У объекта можно прописать особые способы вывода и изменения значения какого-либо поля
  • Пример
    	var person = {
    		_age: 20,
    		get age(){
    			return this._age
    		},
    		set age(value){
    			this._age = value
    		}
    	};
    
  • Получается, что в случае вызова person.age() без параметра вернется текущее значение _age, а в случае вызова с параметром изменит значение на значение входного параметра

Properties

  • Пример
    	Object.defineProperty(person, "gender", {
    		value: "male",
    		writable: false,
    		enumerable: false,
    		configurable: false
    	});
    
    - меняет атрибуты свойства gender у объекта person
  • Object.getOwnPropertyDescriptor(person, "gender"); - вернет значения атрибутов свойства
    • value - значение поля
    • writable - можно ли менять значение поля
    • enumerable - будет ли это поле перечислено при выводе всех полей объекта (не влияет на console.log(obj);)
    • configurable - можно ли менять любое из выше упомянутых значений (+ его само)
  • Код
    	for(property in person) {
    		console.log(property);
    	};
    
    - обходит поля объекта с enumerable: true (и свои, и наследованные)
  • Object.keys(person); - вернет массив всех полей с enumerable: true (и свои, и наследованные)
  • person.propertyIsEnumerable("gender"); - возвращает значение enumerable для поля (может вернуть true только для своих полей)
  • Можно менять атрибуты свойств массово:
    	Object.defineProperty(obj, {
    		x: {
    			value: 10,
    			writable: false
    		},
    		...
    	});
    
  • Object.preventExtensions(obj); - запрещает расширение объекта (добавление новых полей)
  • Object.isExtensible(obj); - можно ли расширять объект
  • Object.seal(obj); - аналогично Object.preventExtensions(obj), но также ставит configurable: false для всех полей
  • Object.isSealed(obj); - был ли применен Object.seal(obj)
  • Object.freeze(obj); - аналогично Object.seal(obj), но также ставит writable: false для всех полей
  • Object.isFrozen(obj); - был ли применен Object.freeze(obj)

Prototypes, Inheritance, Constructors, Classes

  • Создадим объект, который будет являться прототипом для других объектов. Он ничем не отличается от стандартного объекта: var objProto = { name: "John" };
  • Теперь создадим новый объект на основе этого прототипа: var obj = Object.create(objProto);
  • Как и следовало ожидать obj унаследовал поле name со значением "John", но своего такого поля не имеет
  • Проверить соответствие прототипа и объекта можно так: objProto.isPrototypeOf(obj);
  • Допустим вы хотите какое-то сложное создание объекта на основе прототипа, а не простое наследование всех его полей. В таком случае можно использовать конструктор
  • Конструктор - это функция, которая берет передаваемые в неё значения и записывает их в поля нового объекта. Перед записью с входными параметрами можно проделывать преобразования и вообще что-угодно
  • Конструктор
    	var objProto = function(name, age, gender) {
    		this.name = name;
    		this.age = age;
    		this.gender = gender;
    	};
    
  • var obj = new objProto("John", 35, "male"); - так мы вызываем этот конструктор и передаем ему необходимые входные параметры
  • Доступ к прототипу функции конструктора может быть получен через objProto.prototype;
  • Можно привязать какой-нибудь метод или свойство на прототип функции конструктора и этот метод или свойство станут доступны всем объектам, созданным этим конструктором
  • Чтобы получить доступ к конструктору объекта, которым он был создан: obj.constructor;
  • obj instanceof objProto; - определяет этим ли конструктором был создан объект (определяется через constructor объекта)
  • Прямой не рекомендуемый способ получения прототипа объекта: obj.__proto__;
  • Через обращение к прототипам можно изменять нативные (встроенные) функции языка JS
  • Само понятие класса неуместно для языка JS, но это объекты, созданные конструкторами

Chain Calls

  • Это поочередный вызов методов. Так как методы возвращают результат преобразований в точку их вызова, именно для результата вызывается следующий метод и так далее
  • string = "Sometimes the same is different";
  • newString = string.replace("is", "is not").concat(" actually").toUpperCase();

JSON

  • Для передачи массивов данных через текст используются преобразованные в строку объекты. Это и есть JSON
  • var user = { name: "John" };
  • var userData = JSON.stringify(user); - преобразует объект в строку. Стандартный метод toString() вместо описания объекта вернет [object Object], поэтому он не подходит
  • JSON.parse(userData); - преобразовывает строку в объект
  • Если в объекте будет определен метод toJSON, то преобразование будет происходить с помощью него
    	user = {
    		name: "John",
    		toJSON: function(){
    			return {
    				name: this.name.toUpperCase()
    			}
    		}
    	};
    

Arrays

  • var arr = [1, 2, 3, 4];
  • arr[2]; // 3
  • arr[5]; // undefined
  • arr.length; - число элементов массива. На самом деле вернет самый большой индекс со значением не undefined +1
  • Для того, чтобы записать в конец массива, можно использовать хитрость: arr[arr.length] = 5;
  • Элементы не обязаны идти под последовательными индексами: arr[10] = 10;
  • Это приведет к созданию следующего массива: [1, 2, 3, 4, 5, undefined, undefined, undefined, undefined, undefined, 10];
  • Такие массивы называют разреженными
  • var myArr = new Array(); - создание массива
  • new Array(5); - если указать один входной параметр, то он будет размером массива
  • new Array(1, 2, 3); - если несколько, то они будут элементами этого массива
  • arr = [,,,23]; - массив с 3 неопределенными элементами
  • arr = [,,]; - массив с 2 элементами (так как запятая после последнего элемента синтаксически допускается)
  • По сути массив - это объект, у которого есть поля с названиями в виде целых неотрицательных чисел и их значения
  • То есть возможно и следующее: arr["some"] = 1;
  • Но так как метод length ожидает, что элементы будут лишь под неотрицательными целочисленными индексами, то создание элементов под индексами отрицательных или не целых чисел или строк не будет влиять на значение length
  • Если поменять значение length на меньшее, то будут удалены все элементы превышающие значение (length-1) по индексу. При этом элементы под "нелегальными" индексами затронуты не будут
  • delete array[3]; - удаляет элемент и оставляет на его месте undefined, никакие элементы никуда не сдвинутся
  • Array.isArray(arr); - является ли массивом
  • arr.join(); - объединяет все элементы массива в строку с разделителем, переданным в скобки. По-умолчанию, это запятая без пробела
  • arr.reverse(); - переворачивает массив (меняет исходные данные)
  • arr.sort(); - сортирует исходный массив (сортировка идет на основе строкового представления элементов)
  • arr.concat("Hello", ["Even", "More"]); - возвращает новый массив, складывая старый массив и аргументы
  • arr.slice(1); - обрезает массив от его начала на количество элементов, указанное в скобках. Не изменяет исходный массив, возвращает то, что останется после обрезания
  • arr.splice(1, 2, "John", "Frank"); - изменяет исходный массив, вырезает из массива 2 элемента, начиная с элемента под индексом 1, и вставляет на их место "John" и "Frank". Можно ничего не вставлять на место вырезанных элементов. Хоть splice и меняет исходный массив, возвращает он именно вырезанные элементы
  • arr.push("Sam"); - добавить элемент в конец массива
  • arr.unshift("Jack"); - добавить элемент в начало массива (сдвигает индексы всех остальных элементов)
  • arr.pop(); - удаляет последний элемент массива и возвращает его
  • arr.shift(); - удаляет первый элемент массива и возвращает его (сдвигает индексы всех остальных элементов)
  • arr.forEach(function(element, index, array){ ... }); - для каждого элемента массива. element - значение элемента, index - его индекс, array - массив, который перебирают
  • arr.map(function(e){ return e.toUpperCase(); }); - возвращает массив элементов из arr, но преобразованных. e - значение элемента
  • arr.filter(function(e){ return e.indexOf('o') === -1; }); - возвращает массив, отфильтрованный функцией. Если return вернул true - то элемент будет в массиве, если false - нет
  • arr.reject(); - аналог фильтра, но работает наоборот
  • arr.every(function(e){ return e.length > 1; }); - проходит по всем элементам, проверяет условие из return, и, если все элементы вернули true, то вернет true. Если хотя бы один вернул false, то вернет false
  • arr.some(function(e){ return e.indexOf('z') !== -1; }); - true, если хотя бы один удовлетворяет условию. false, если ни одного
  • arr.reduce(function(a, b){ return a+b; }); - обходит массив по элементам, но на первой итерации берет первый и второй элементы, они записываются в a и b. На второй итерации в a хранится значение, которое вернула функция на первой итерации, а в b хранится третий элемент. На последней итерации return возвращает результат в место вызова функции
  • Также можно написать следующее: arr.reduce(function(a, b){ return a+b; }, 0); - тогда на первой итерации в a будет хранится 0, а в b - первый элемент массива. Далее аналогично первому объяснению выше
  • Также можно обходить массив с конца в начало: arr.reduceRight();
  • arr.indexOf("z"); - находит индекс первого элемента с таким значением, начиная с начала массива
  • arr.lastIndexOf("z"); - начиная с конца массива

Math

  • Math.pow(2, 5); - возведение числа 2 в степень 5
  • Math.sqrt(9); - квадратный корень
  • Math.abs(-300); - модуль
  • Math.round(9.5); - правильное округление
  • Math.floor(9.5); - округление в меньшую сторону
  • Math.ceil(9.5); - округление в большую сторону
  • Math.min(1, 2, 3); - минимальное число из аргументов
  • Math.max(1, 2, 3); - максимальное
  • Math.exp(2); - возводит e в степень 2
  • Math.log(5); - натуральный логарифм числа 5
  • Math.sin(2), cos, tan, atang, asin, acos; - соответствующие математические функции, входные параметры в радианах
  • Math.PI, Math.E - математические константы
  • Math.LN10; - логарифм 10
  • Math.LN2; - логарифм 2
  • Math.SQRT2; - квадратный корень из 2
  • Math.SQRT1_2; - квадратный корень из 1/2
  • Math.random(); - произвольное число от 0 до 1

Date

  • var date = new Date(); - текущее время
  • new Date(1990, 0, 1, 10, 24, 22, 345); - год, месяц (почему-то с нуля), день, час, минута, секунда, миллисекунда
  • date.getMilliseconds(); - вернет миллисекунды
  • date.getSeconds();
  • date.getMinutes();
  • date.getHours();
  • date.getDay(); - день недели
  • date.getDate(); - номер дня в месяце
  • date.getMonth();
  • date.getYear(); - год, последние 2 цифры
  • date.getFullYear(); - год, все 4 цифры
  • Для всех get есть и set, кроме getDay, что логично
  • date.getTime(); - количество миллисекунд с начала 1970 года. Если раньше, то число отрицательное
  • Всё время и даты относительно GMT. Для работы с UTC: getUTCHours(); и так далее
  • date.toTimeString(); - только время
  • date.toDateString(); - только дата
  • date.toLocaleTimeString(); - только время с учетом локации и часовых поясов
  • date.toLocaleDateString(); - только дата
  • Date.now(); - количество миллисекунд с начала 1970 года до текущего момента времени

Regular Expressions

  • Регулярные выражения служат для поиска совпадений по определенным маскам, которыми они и являются. Искать таким образом можно, например, строки. Дальше будет несколько примеров с объяснениями, что они делают. Полного перечисления всех возможностей не будет, так как они легко ищутся в интернете и нет смысла тупо их копировать
  • /kill/ - найти в точности такой текст (kill)
  • [aoeiuy] - найти все эти буквы по отдельности
  • \w - все буквы и цифры
  • \W - всё, кроме букв и цифр
  • \d - все цифры
  • \D - всё, кроме цифр
  • Пример: /kill\d/gim - / это ограничители регулярного выражения /, всё что внутри будет искаться. После ограничителей идут флаги поиска. g - глобальный поиск, а не только первого совпадения, i - нерегистрозависимый поиск, m - многострочный поиск (то есть, если искомая фраза началась на одной строке, а закончилась на другой - то всё нормально найдется, если есть этот флаг)
  • Регулярные выражения можно использовать через их литералы, а можно и создать как объект
  • var pattern = new RegExp("\w", "gim"); - само регулярное выражение и его флаги
  • var samePattern = /\w/gim; - аналогично
  • string = "bla bla";
  • string.match(pattern); - вернет массив всего, что удовлетворяет регулярному выражению. Если из регулярки убрать флаг g, то выдаст лишь первое совпадение с указанием индекса в строке
  • string.search(pattern); - всегда игнорирует флаг g, возвращает индекс первого совпадения. -1, если ничего не найдено
  • Регулярные выражения можно передавать как входные параметры на функции, что может решать некоторые нетривиальные задачи довольно простым образом
  • pattern.global, pattern.ignoreCase, pattern.multiline - проверки наличия флагов
  • pattern.lastIndex; - хранит индекс последнего результата
  • pattern.test(string); - есть ли регулярка в строке
  • pattern.exec(string); - поиск совпадения и его положения

Strict Mode

  • 'use strict'; - инициализация Strict мода
  • Может быть прописан где-угодно и будет работать именно там
  • Блокирует использование "плохих" функций
  • this указывает на undefined
  • Необходимо всегда объявлять переменные через var
  • Запрещено пытаться переписать значение поля с writable: false
  • Запрещено пытаться добавлять поля к нерасширяемому объекту
  • Запрещено пытаться удалять поля с configurable: false
  • В литералах объектов запрещены поля с одинаковыми названиями
  • Запрещены восьмеричные числа

Browser Shit

  • alert("Hi"); - окошко с текстом и кнопкой Ok, блокирует дальнейшее выполнение скрипта и весь контент сайта
  • document - объект HTML-разметки
  • document.getElementById('content'); - получить элемент по его ID из разметки, но внутри элемента document (можно искать не во всей разметке, а внутри определенного элемента). Вернёт разметку именно этого элемента. То есть <button id="content">Кнопка</button>
  • document.getElementsByTagName('div'); - получить все элементы по тегу. Также можно найти вообще все элементы, если передать '*'. Метод возвращает коллекцию элементов (что-то типа массива), поэтому нужно указывать к какому именно элементу вы обращаетесь (по индексу [0] как в массивах)
  • Также существуют методы для доступа по атрибуту name, по классу, по CSS-селектору и куча прочего мусора
  • window - глобальный объект браузера. Тут висят все глобальные переменные из скриптов со страницы
  • window.addEventListener("mousemove", function(e){ console.log("X"+e.offsetX, "Y"+e.offsetY) }); - добавляет Listener (слушателя, который ждет событие, тип которого указан в кавычках). Когда событие происходит, слушатель отлавливает все данные этого события и передает их в функцию через переменную e (название может быть любое). Затем в этих данных (которые являются объектом), мы обращаемся к полям offsetX и offsetY, в которых хранятся координаты мыши относительно верхней левой точки окна браузера (не всего окна, а только той области, в которой отображаются сайты). Есть множество типов событий, конкретно здесь используется движение мыши
  • setTimeout(function(){ console.log("Hi"); }, 2000); - однократное выполнение функции с задержкой в 2 секунды (время указывается в миллисекундах)
  • Чтобы была возможность отменить это выполнение, необходимо занесение в переменную: var timeOut = setTimeout(...);
  • clearTimeout(timeOut); - отмена выполнения
  • setInterval(...); - многократное выполнение с задержкой
  • clearInterval(...); - отмена
  • confirm("What"); - окошко с текстом и кнопка Ok и Cancel
  • Если написать var conf = confirm("What"); то значение conf будет зависеть от нажатой кнопки
  • prompt("Your age?"); - окошко с вводом, аналогично confirm можно отлавливать значения
  • var w = window.open("http://google.com"); - открыть сайт в другом окне (почти всегда блокируется как реклама)
  • window.close(w); - закрывает. Закрыть можно только то, что было открыто вами
  • window.location; - объект адресной строки. Можно обращаться и по имени location, но не рекомендуется
  • window.location.hash; - всё, что после #
  • Изменение hash, да и вообще почти всего можно не только через слушателей, но и через короткие записи слушателей
  • window.onclick, window.onchange, window.onhashchange = function(e){...};
  • window.location.href; - полный адрес сайта
  • window.location.toString(); - вернет именно window.location.href
  • window.location.search; - всё, что после ?
  • window.location.reload(); - перезагрузка страницы
  • window.location.assign("http://google.com"); - пересылает на указанный сайт
  • window.location = "http://google.com"; - аналогично
  • window.location.replace("http://google.com"); - аналогично, но также заменяет изначальный адрес сайта в истории браузера на новый
  • encodeURI("текст"); - заменяет не ASCI-символы на escape-последовательности (кодирует)
  • decodeURI("текст"); - раскодирует
  • e.preventDefault; - отменяет действие по-умолчанию у e (e обычно является отловленным через слушатель событием)
  • screen.width, screen.height - размеры экрана пользователя
  • screen.availWidth, screen.availHeight - размеры рабочей области браузера (там где отображаются сайты)