Циклы в javascript (while, do … while, for)

10) addEvent()

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

function addEvent(elem, evType, fn) {
	if (elem.addEventListener) {
		elem.addEventListener(evType, fn, false);
	}
	else if (elem.attachEvent) {
		elem.attachEvent('on' + evType, fn)
	}
	else {
		elem = fn
	}
}

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

Основной его недостаток — в том, он не передает в обработчик для IE. Точнее, этого не делает .

Для передачи правильного this можно заменить соответствующую строку на:

elem.attachEvent("on"+evType, function() { fn.apply(elem) })

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

Существует два варианта обхода проблемы:

  1. Возвращать функцию, использованную для назначения обработчика:
    function addEvent(elem, evType, fn) {
    	if (elem.addEventListener) {
    		elem.addEventListener(evType, fn, false)
                    return fn
    	}
    
            iefn = function() { fn.call(elem) } 
            elem.attachEvent('on' + evType, iefn)
    	return iefn
    }
    
    function removeEvent(elem, evType, fn) {
    	if (elem.addEventListener) {
    		elem.removeEventListener(evType, fn, false)
                    return
    	}
     
            elem.detachEvent('on' + evType, fn)
    }
    

    Используется так:

    function handler() { 
        alert(this) 
    }
    var fn = addEvent(elem, "click", handler)
    ...
    removeEvent(elem, "click", fn)
    
  2. Можно не использовать в обработчике события вообще, а передавать элемент через замыкание:

    function handler() { 
       // используем не this, а переменную, ссылающуюся на элемент
        alert(*!*elem*/!*) 
    }
    ...
    

В качестве альтернативы и для примера более серьезной библиотеки обработки событий вы можете рассмотреть статью Кросс-браузерное добавление и обработка событий.

More Examples

Example

Loop through the indices of an array to collect the car names from the cars
array:

var cars = ;var text = «»;var i;for (i = 0; i < cars.length; i++) {  text += cars + «<br>»;
}

Example above explained:

  • First, we set a variable before the loop starts (var i = 0;)
  • Then, we define the condition for the loop to run. As long as the variable is less than the length of the array (which is 4), the loop will continue
  • Each time the loop executes, the variable is incremented by one (i++)
  • Once the variable is no longer less than 4 (array’s length), the condition is false, and the loop will end

Example

Initiate multiple values in the first parameter:

var cars = ;var i;for (i = 0, len = cars.length, text = «»; i < len; i++) {   text += cars + «<br>»;
}

Example

Omit the first parameter (set values before the loop starts):

var cars = ;var i = 2;var len = cars.length;var text = «»;for (; i < len; i++) {
  text += cars + «<br>»;
}

Example

Using the continue statement — Loop through a block of code, but skip the value of «3»:

var text = «»;var i;for (i = 0; i < 5; i++) {  if (i == 3) {    continue;
  }  text += «The number is » + i + «<br>»;}

Example

Using the break statement — Loop through a block of code, but exit the loop when the variable i is equal
to «3»:

var text = «»;var i;for (i = 0; i < 5; i++) {  if (i == 3) {
    break;  }  text += «The number is » + i + «<br>»;}

Example

Omit the second parameter. In this example, we also use the break statement to exit the loop when i is equal to «3» (if the second parameter is omitted, you must provide a break
inside the loop. Otherwise the loop will never end, and your browser will crash):

var cars = ;var text = «»;
var i;for (i = 0; ; i++) {  if (i == 3) {    break;
  }  text += cars + «<br>»;}

Example

Loop through the indices of an array, in descending order (negative
increment):

var cars = ;var text = «»;var i;
for (i = cars.length — 1; i >= 0; i—) {  text += cars + «<br>»;
}

Example

Omit the last parameter, and increment the values inside the loop:

var cars = ;var i = 0;var len = cars.length;for (; i < len;) {   text += cars + «<br>»;
 
i++;}

Example

Loop through the nodes of a NodeList object and change the background color of all <p> elements in the list:

var myNodelist = document.getElementsByTagName(«P»);var i;for (i = 0; i < myNodelist.length; i++) {  myNodelist.style.backgroundColor = «red»;}

Example

An example of a nested loop (a loop inside a loop):

var text = «»;var i, j;for (i = 0; i < 3; i++) {  text += «<br>» + «i = » + i + «, j = «;
  for (j = 10; j < 15; j++) {    document.getElementById(«demo»).innerHTML = text += j + » «;
  }}

Что такое JavaScript?

Изначально JavaScript был создан, чтобы «сделать веб-страницы живыми».

Программы на этом языке называются скриптами. Они могут встраиваться в HTML и выполняться автоматически при загрузке веб-страницы.

Скрипты распространяются и выполняются, как простой текст. Им не нужна специальная подготовка или компиляция для запуска.

Это отличает JavaScript от другого языка – Java.

Почему JavaScript?

Когда JavaScript создавался, у него было другое имя – «LiveScript». Однако, язык Java был очень популярен в то время, и было решено, что позиционирование JavaScript как «младшего брата» Java будет полезно.

Со временем JavaScript стал полностью независимым языком со своей собственной спецификацией, называющейся ECMAScript, и сейчас не имеет никакого отношения к Java.

Сегодня JavaScript может выполняться не только в браузере, но и на сервере или на любом другом устройстве, которое имеет специальную программу, называющуюся «движком» JavaScript.

У браузера есть собственный движок, который иногда называют «виртуальная машина JavaScript».

Разные движки имеют разные «кодовые имена». Например:

  • V8 – в Chrome и Opera.
  • SpiderMonkey – в Firefox.
  • …Ещё есть «Trident» и «Chakra» для разных версий IE, «ChakraCore» для Microsoft Edge, «Nitro» и «SquirrelFish» для Safari и т.д.

Эти названия полезно знать, так как они часто используются в статьях для разработчиков. Мы тоже будем их использовать. Например, если «функциональность X поддерживается V8», тогда «Х», скорее всего, работает в Chrome и Opera.

Как работают движки?

Движки сложны. Но основы понять легко.

  1. Движок (встроенный, если это браузер) читает («парсит») текст скрипта.
  2. Затем он преобразует («компилирует») скрипт в машинный язык.
  3. После этого машинный код запускается и работает достаточно быстро.

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

Function Expression в сравнении с Function Declaration

Давайте разберём ключевые отличия Function Declaration от Function Expression.

Во-первых, синтаксис: как определить, что есть что в коде.

  • Function Declaration: функция объявляется отдельной конструкцией «function…» в основном потоке кода.

  • Function Expression: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части «выражения присваивания» :

Более тонкое отличие состоит, в том, когда создаётся функция движком JavaScript.

Function Expression создаётся, когда выполнение доходит до него, и затем уже может использоваться.

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

С Function Declaration всё иначе.

Function Declaration можно использовать во всем скрипте (или блоке кода, если функция объявлена в блоке).

Другими словами, когда движок JavaScript готовится выполнять скрипт или блок кода, прежде всего он ищет в нём Function Declaration и создаёт все такие функции. Можно считать этот процесс «стадией инициализации».

И только после того, как все объявления Function Declaration будут обработаны, продолжится выполнение.

В результате, функции, созданные, как Function Declaration могут быть вызваны раньше своих определений.

Например, так будет работать:

Функция была создана, когда движок JavaScript подготавливал скрипт к выполнению, и такая функция видна повсюду в этом скрипте.

…Если бы это было Function Expression, то такой код вызовет ошибку:

Функции, объявленные при помощи Function Expression, создаются тогда, когда выполнение доходит до них. Это случится только на строке, помеченной звёздочкой . Слишком поздно.

Ещё одна важная особенность Function Declaration заключается в их блочной области видимости.

В строгом режиме, когда Function Declaration находится в блоке , функция доступна везде внутри блока. Но не снаружи него.

Для примера давайте представим, что нам нужно создать функцию в зависимости от значения переменной , которое мы получим во время выполнения кода. И затем запланируем использовать её когда-нибудь в будущем.

Такой код, использующий Function Declaration, работать не будет:

Это произошло, так как объявление Function Declaration видимо только внутри блока кода, в котором располагается.

Вот ещё один пример:

Что можно сделать, чтобы была видима снаружи ?

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

Такой код работает, как ожидалось:

Можно упростить этот код ещё сильнее, используя условный оператор :

Когда использовать Function Declaration, а когда Function Expression?

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

Также функции вида чуть более заметны в коде, чем . Function Declaration легче «ловятся глазами».

…Но если Function Declaration нам не подходит по какой-то причине (мы рассмотрели это в примере выше), то можно использовать объявление при помощи Function Expression.

Нечисловые свойства

Массивы JavaScript являются объектами. Это означает, что вы можете добавлять строковые свойства в ваш массив, а не только числа.

const arr = ;

typeof arr; // 'object'

// Assign to a non-numeric property
arr.test = 'bad';

arr.test; // 'abc'
arr === arr; // true, JavaScript arrays are just special objects

Три из четырех циклических конструкций игнорируют нечисловое свойство. Однако for/in фактически выведет слово «bad»:

const arr = ;
arr.test = 'bad';

// Prints "a, b, c, bad"
for (let i in arr) {
  console.log(arr);
}

Вот почему перебор массива с использованием for/in — это, как правило, плохая практика. Другие циклические конструкции правильно игнорируют нечисловой ключ:

const arr = ;
arr.test = 'abc';

// Prints "a, b, c"
for (let i = 0; i < arr.length; ++i) {
  console.log(arr);
}

// Prints "a, b, c"
arr.forEach((el, i) => console.log(i, el));

// Prints "a, b, c"
for (const el of arr) {
  console.log(el);
}

Вывод: избегайте использования for/in для массива, если вы не уверены, что хотите перебрать нечисловые ключи или унаследованные ключи. Используйте правило ESLint для запрета for/in конструкций.

Переход к следующей итерации: continue

Директива – «облегчённая версия» . При её выполнении цикл не прерывается, а переходит к следующей итерации (если условие все ещё равно ).

Её используют, если понятно, что на текущем повторе цикла делать больше нечего.

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

Для чётных значений , директива прекращает выполнение тела цикла и передаёт управление на следующую итерацию (со следующим числом). Таким образом вызывается только для нечётных значений.

Директива позволяет избегать вложенности

Цикл, который обрабатывает только нечётные значения, мог бы выглядеть так:

С технической точки зрения он полностью идентичен. Действительно, вместо можно просто завернуть действия в блок .

Однако мы получили дополнительный уровень вложенности фигурных скобок. Если код внутри более длинный, то это ухудшает читаемость, в отличие от варианта с .

Нельзя использовать справа от оператора „?“

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

Например, если мы возьмём этот код:

…и перепишем его, используя вопросительный знак:

…то будет синтаксическая ошибка.

Это ещё один повод не использовать оператор вопросительного знака вместо .

Конструкции

Как и во многих языках, предложения на языке javascript можно разделять точкой с запятой.

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

Эти две строки полностью эквивалентны:

a = 5
a = 5;

В частности, многие новички сталкиваются с ошибками при многострочных присваиваниях и вызовах.

Вот так не будет работать:

var a = "длинная 
  строка "

Так как перевод строки подразумевает точку с запятой, и javascript поймет это как

var a = "длинная;
  строка ";

То есть, сообщит о незавершенной строке (unterminated literal) в первой строчке этого примера.

Или, например, следующие два примера кода эквивалентны:

return
  result;

то же самое, что и

return;
result;

и совсем не то же, что

return result

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

Чтобы многострочные операторы работали как надо — перенос строки можно указывать обратным слешем «\», вот так:

var a = "длинная \
  строка "

return \
   result;

Полный список синтаксических конструкций и операторов приведен в справочнике. Они похожи на PHP/C/Java, но многие имеют особенности, знание которых поможет грамотно программировать на javascript.

Блоки задаются фигурными скобками.

Локальные переменные объявляются при помощи var. Причем, в отличие от C/Java, сам по себе блок не задает отдельную область видимости.

var i = 0
{
  var i=5
  alert(i) // 5 
}
alert(i) // тоже 5

Комментарии возможны в двух вариантах и

// однострочные комментарии 

/* 
   многострочные
   комментарии
*/

ИЛИ «||» находит первое истинное значение

Описанная выше логика соответствует традиционной. Теперь давайте поработаем с «дополнительными» возможностями JavaScript.

Расширенный алгоритм работает следующим образом.

При выполнении ИЛИ || с несколькими значениями:

Оператор выполняет следующие действия:

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

Значение возвращается в исходном виде, без преобразования.

Другими словами, цепочка ИЛИ возвращает первое истинное значение или последнее, если такое значение не найдено.

Например:

Это делает возможным более интересное применение оператора по сравнению с «чистым, традиционным, только булевым ИЛИ».

  1. Получение первого истинного значения из списка переменных или выражений.

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

    С помощью :

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

  2. Сокращённое вычисление.

    Операндами могут быть как отдельные значения, так и произвольные выражения. ИЛИ вычисляет их слева направо. Вычисление останавливается при достижении первого истинного значения. Этот процесс называется «сокращённым вычислением», поскольку второй операнд вычисляется только в том случае, если первого недостаточно для вычисления всего выражения.

    Это хорошо заметно, когда выражение, указанное в качестве второго аргумента, имеет побочный эффект, например, изменение переменной.

    В приведённом ниже примере не изменяется:

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

    Присваивание – лишь один пример. Конечно, могут быть и другие побочные эффекты, которые не проявятся, если вычисление до них не дойдёт.

    Как мы видим, этот вариант использования является «аналогом «. Первый операнд преобразуется в логический. Если он оказывается ложным, начинается вычисление второго.

    В большинстве случаев лучше использовать «обычный» , чтобы облегчить понимание кода, но иногда это может быть удобно.

Цикл for

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

Описание синтаксиса:

  1. Инициализация. Присваивается первоначальное значение переменной, обычно – счетчика. Выполняется только один раз в начале выполнения оператора. Областью действия этой переменной будет тело цикла.
  2. Выражение – булево выражение, которое вычисляется на каждой итерации цикла. Представляет собой условие продолжения работы оператора цикла. После того, как значение счетчика достигнет указанного предела, цикл завершится.
  3. Обновление – это значение, на которое будет увеличиваться или уменьшаться счетчик цикла. Вычисляется по завершении каждой итерации цикла. Чтобы оно было полезным, как и выражение инициализации, оно должно иметь побочные эффекты. В общем случае таким побочным эффектом служит операция присваивания, инкремента или декремента.

Пример цикла for:

Выполнить код »
Скрыть результаты

Рассмотрим выполнение этого цикла более подробно:

  1. Инициализация: Переменная-счетчик, в данном случае х, инициализируется значением 1. Выполняется один-единственный раз, при заходе в цикл.
  2. Выражение: x – это условие продолжения цикла for, оно проверяется перед каждой итерацией и при входе в цикл на истинность. Если это так, то выполняются инструкции тела цикла (в данном случае – инструкция alert( x + » » );).
  3. Обновление: x++ – изменяет значение переменной-счетчика. Выполняется после тела на каждой итерации, но перед проверкой условия x .
  4. Тело цикла: alert( x + » » ) – тело цикла обрамляется фигурными скобками, если тело цикла состоит из одной операции, то фигурные скобки можно опустить.

Иными словами, поток выполнения цикла: Инициализация → (если условие выражения → тело цикла → обновление (x++)) → (если условие выражения → тело цикла → обновление (x++)) → … и так далее, пока верно условие – x .

Циклы for могут быть более сложными, чем в приведенных выше примерах. В некоторых циклах на каждой итерации может изменяться одновременно несколько переменных. В таких циклах часто применяется оператор «запятая» – он позволяет объединить несколько выражений инициализации и инкрементирования в одно, например:

Выполнить код »
Скрыть результаты

let

У объявлений переменной через есть три основных отличия от :

  1. Область видимости переменной – блок .

    Как мы помним, переменная, объявленная через , видна везде в функции.

    Переменная, объявленная через , видна только в рамках блока , в котором объявлена.

    Это, в частности, влияет на объявления внутри , или .

    Например, переменная через :

    В примере выше – одна переменная на весь код, которая модифицируется в .

    То же самое с будет работать по-другому:

    Здесь, фактически, две независимые переменные , одна – глобальная, вторая – в блоке .

    Заметим, что если объявление в первой строке удалить, то в последнем будет ошибка: переменная не определена:

    Это потому что переменная всегда видна именно в том блоке, где объявлена, и не более.

  2. Переменная видна только после объявления.

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

    С переменными всё проще. До объявления их вообще нет.

    Такой доступ приведёт к ошибке:

    Заметим также, что переменные нельзя повторно объявлять. То есть, такой код выведет ошибку:

    Это – хоть и выглядит ограничением по сравнению с , но на самом деле проблем не создаёт. Например, два таких цикла совсем не конфликтуют:

    При объявлении внутри цикла переменная будет видна только в блоке цикла. Она не видна снаружи, поэтому будет ошибка в последнем .

  3. При использовании в цикле, для каждой итерации создаётся своя переменная.

    Переменная – одна на все итерации цикла и видна даже после цикла:

    С переменной – всё по-другому.

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

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

    Если бы объявление было , то была бы одна переменная на всю функцию, и вызовы в последних строках выводили бы (подробнее – см. задачу Армия функций).

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

Условный оператор „?“

Иногда нам нужно определить переменную в зависимости от условия.

Например:

Так называемый «условный» оператор «вопросительный знак» позволяет нам сделать это более коротким и простым способом.

Оператор представлен знаком вопроса . Его также называют «тернарный», так как этот оператор, единственный в своём роде, имеет три аргумента.

Синтаксис:

Сначала вычисляется : если оно истинно, тогда возвращается , в противном случае – .

Например:

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

Этот пример будет делать то же самое, что и предыдущий:

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

В примере выше вы можете избежать использования оператора вопросительного знака , т.к. сравнение само по себе уже возвращает :

Как сделать Object и простые объекты итерируемыми

Простые объекты не являются итерируемыми, как и объекты из .

Однако этот момент можно обойти, добавив @@iterator к Object.prototype с пользовательским итератором.

Переменная  содержит свойства объекта, полученного с помощью вызова . В функции next возвращается каждое значение из переменной properties и обновляется count, чтобы получить следующее значение из переменной properties, используя переменную count в качестве индекса. Когда count будет равен длине properties, устанавливаем значение true, чтобы остановить итерацию.

Тестирование с помощью Object:

Работает!!!

С простыми объектами:

Та-дам!! 

Стоить добавить этот способ в качестве полифилла, чтобы использовать for..of с любыми объектами в приложении.

Использование for…of с классами ES6

Можно использовать for..of для итерации по списку данных в экземпляре класса.

Класс Profiles обладает свойством , которое содержит массив пользователей. Возможно, потребуется отобразить эти данные в приложении с помощью for…of. Пробуем:

Очевидно, for…of не сработает

Вот несколько правил, чтобы сделать  итерируемым:

  • Объект должен иметь свойство .
  • Функция  должна возвращать итератор.
  •  должен реализовывать функцию .

Свойство @@iterator определяется с помощью константы .

Запускаем:

Свойство profiles отображено.

JavaScript

JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()

JS Boolean
constructor
prototype
toString()
valueOf()

JS Classes
constructor()
extends
static
super

JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()

JS Error
name
message

JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()

JS JSON
parse()
stringify()

JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
clz32()
cos()
cosh()
E
exp()
expm1()
floor()
fround()
LN2
LN10
log()
log10()
log1p()
log2()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sign()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()

JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()

JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()

(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx

JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while

JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()

Область видимости

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

Локальная переменная объявляется так:

var i

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

// то же самое что 3 отдельных объявления c var
var a=5, b=6, str = "Строка"

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

a = 1
function go() {
    var a = 6
}

go()
alert(a) // => 1

А здесь — ключевое слово опущено, поэтому значение меняется:

a = 1
function go() {
    a = 6
}

go()
alert(a) // => 6

Кстати, глобальных переменных в javascript на самом деле нет. То, что называют «глобальными» — на самом деле свойства специального объекта window. Например, в последнем примере тоже выдало бы .

Все «глобальные» переменные привязаны к своему окну. Разные окна и фреймы имеют разные «глобальные» переменные, которыми могут обмениваться друг с другом.

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

Как правило — всё, что относится к компоненту, объявляется в виде свойств единого глобального объекта: ExtJS, dojo и т.п. Вы можете увидеть это в любом известном JS-фреймворке.

Обратите внимание, в javascript все директивы var срабатывают при входе в функцию, неважно где они находятся. Например, посмотрим на функцию:

Например, посмотрим на функцию:

function cmp(a,b) {
  if (a>b) {
    res = 1
  } else if (a<b) {
    res = -1
  } else {
    var res = 0
  }
  
  return res
}

При входе в функцию интерпретатор javascript находит все объявления и создает соответствующие локальные переменные.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector