#js — Не работает функция на JS


Содержание

3 способа запуска функции или кода Javascript (js) при загрузке страницы.

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

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

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

К элементу с id #block не будет применяться правило css (background-color:yellow), т.к. строка

Будет выполняться раньше, чем загрузиться html-строка:

Как быть, если нам нужно выполнить код или функцию, только после того, как весь документ полностью загрузится?

Я хочу рассказать о трех способах, как это можно сделать.

1 способ. С использованием библиотеки Jquery.

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

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

2 способ. С помощью элемента body и атрибута onload.

3 способ. С помощью объекта window и его свойства onload.

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

Почему функция map не работает с некоторыми массивами в JavaScript и что с этим делать

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

Сценарий

Для более наглядной демонстрации предположим, что вам нужно сгенерировать массив чисел от 0 до 99. Как можно это сделать? Например, так:

Возможно, цикл for в JavaScript заставляет вас чувствовать себя неуютно. На самом деле, многие программисты годами не используют for -циклы благодаря функциям forEach() , map() , filter() , и reduce() . Декларативное функциональное программирование рулит!

Если вы еще не поддались массовому помешательству на почве функционального программирования, решение выше кажется вам абсолютно нормальным. Технически так и есть, но распробовав магию функций высшего порядка, вы, скорее всего, подумаете: «Должен быть способ получше».

Тогда первая реакция на проблему может быть такой: «Знаю! Я создам пустой массив длиной 100 и присвою каждому элементу значение его индекса с помощью map() !». JavaScript позволяет создать пустой массив длиной n с помощью функции-конструктора:

Великолепно, не так ли? У нас есть массив длиной 100, так что нужно просто присвоить значение индекса каждому элементу:

Что за дела? Первым элементом массива должен был быть 0, но на самом деле это undefined .

Объяснение

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

Пытаясь обратиться к элементу с индексом 0, вы на самом деле обращаетесь к параметру объекта с ключом 0. Это важно, потому что учитывая то, что массив — это объект, и то, как выполняются функции высшего порядка, мы получаем вполне понятную проблему.
Создавая массив с помощью функции-конструктора, вы получаете объект-массив, у которого параметр length равен числу, которое вы задали, но больше в объекте ничего нет. В нем нет индексов.

Вы получаете undefined , пытаясь обратиться к элементу массива с индексом 0, но это не потому, что в элементе с индексом 0 хранится undefined , а потому, что JavaScript всегда возвращает undefined при попытке обратиться к несуществующему элементу массива.
Так устроено, что функции высшего порядка — map() , reduce() , filter() и forEach() — проходятся по индексам от 0 до значения length , но callback-функция вызывается только если в объекте существуют индексы. Это объясняет, почему функция ничего не возвращает, и почему ничего не происходит, когда мы используем функцию map() на массив, в котором нет индексов.

Решение

Теперь легко сделать вывод, что нам нужен массив, чья внутренняя структура содержит индексы для каждого элемента от 0 до length . Лучший способ сделать это — деструктурировать массив в пустой массив.

Деструктуризация массива в пустой массив позволяет получить массив, содержащий undefined в каждом элементе.

Так происходит потому, что оператор деструктуризации проще, чем функция map() . Он просто проходит по массиву (или любому итерируемому объекту) от 0 до length и создает во внешнем массиве новый индекс, содержащий значение, полученное из элемента деструктурированного массива с тем же индексом. JavaScript возвращает undefined при обращении к любому элементу деструктурированного массива (так происходит, потому что в нем отсутствуют элементы и индексы), поэтому мы получаем новый массив, заполненный индексами, и потому доступный для функции map() (а также reduce() , filter() и forEach() ).

Заключение

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

Перестали работать js скрипты


Сообщений 13

1 Artyom91 05.10.2012 10:21

  • Artyom91
  • Свой в доску :)
  • Карма: 0 / 0

Тема: Перестали работать js скрипты

Здравствуйте, всё было хорошо, но в один прекрасный момент перестали работать все js скрипты на сайте. Вообще не понимаю из-за чего это могло произойти, никаких манипуляций не делал, посмотрите _http://icefm.ru

2 admin 05.10.2012 10:28

  • admin
  • АлаичЪ
  • Карма: 143 / 2

Re: Перестали работать js скрипты

Что значит «все js скрипты на сайте»? Что именно отвалилось? У меня все прекрасно работает.

PS Очисти полностью кеш браузера. Или воспользуйся другим браузером с которого ни разу не заходил на сайт.

3 Artyom91 05.10.2012 11:35

  • Artyom91
  • Свой в доску :)
  • Карма: 0 / 0

Re: Перестали работать js скрипты

Хотя нет, не все. Только модульные. У вас проиходит загрузка контента через аякс?

Добавлено: 05-10-2012 17:38:17

Блин, спасибо, зашел через другой браузер всё работает. И как с этим бороться ? У меня девушка тоже заходила у неё тоже не работает. Это у всех пользователей же так будет?


Добавлено: 05-10-2012 17:43:03

Нет, всё таки не работает. Браузер в котором работал, очистил кеш и перестало. что делать?

Добавлено: 05-10-2012 18:35:13

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

4 Hooligan 05.10.2012 14:36

  • Hooligan
  • ТоварисЧЬ!
  • Карма: 31 / 0

Re: Перестали работать js скрипты

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

Скорее всего, у вас конфликтуют js скрипты, гдето в 2-х файлах одна функция вызывается! проверьте!

5 Artyom91 05.10.2012 15:30

  • Artyom91
  • Свой в доску :)
  • Карма: 0 / 0

Re: Перестали работать js скрипты

Скорее всего, у вас конфликтуют js скрипты, гдето в 2-х файлах одна функция вызывается! проверьте!

Врятли, всё работало идеально, изменений никаких не проводилось, вообще бред какой-то. Даже слайдер перестал работать.

6 Kanra 05.10.2012 15:52

  • Kanra
  • Adsumus! Adsumus!
  • Карма: 25 / 0

Re: Перестали работать js скрипты

Врятли, всё работало идеально, изменений никаких не проводилось, вообще бред какой-то. Даже слайдер перестал работать.

Вот это что такое?

Инклудится в шаблон, но то ли нет прав на чтение, то ли нет файла.

7 Artyom91 05.10.2012 16:31

  • Artyom91
  • Свой в доску :)
  • Карма: 0 / 0

Re: Перестали работать js скрипты

Уже что-то, вернул этот скрипт заработал файл /templates/music_template/js/bridge.js. Не работает слайдер и кнопка входа

8 Hooligan 05.10.2012 17:04

  • Hooligan
  • ТоварисЧЬ!
  • Карма: 31 / 0

Re: Перестали работать js скрипты

И вы хотите сказать, что у вас с таким количеством js скриптов, нет пересечений?

Хотя это все слепое ковыряние.

10 Artyom91 05.10.2012 18:35

  • Artyom91
  • Свой в доску :)
  • Карма: 0 / 0


Re: Перестали работать js скрипты

Отключил все js скрипты , не помогает.

11 Hooligan 05.10.2012 18:37

  • Hooligan
  • ТоварисЧЬ!
  • Карма: 31 / 0

Re: Перестали работать js скрипты

Отключил все js скрипты , не помогает.

Вы меня не поняли, нужно отключать по 1 и смотреть результат, заработало или нет, а если вы все отрубили — то у вас ничего работать и не будет!
Для начала, отсортируйте все скрипты, что к чему относится и за что отвечает, а затем уж делайте, то, что я написал выше!
Конфликт функции, 100%!

12 Artyom91 05.10.2012 19:18

  • Artyom91
  • Свой в доску :)
  • Карма: 0 / 0

Re: Перестали работать js скрипты

Вы меня не поняли, нужно отключать по 1 и смотреть результат, заработало или нет, а если вы все отрубили — то у вас ничего работать и не будет!
Для начала, отсортируйте все скрипты, что к чему относится и за что отвечает, а затем уж делайте, то, что я написал выше!
Конфликт функции, 100%!

Я конечно очень рад за помощь, но я уверен на 100% что копать нужно не там. Просто понимаете, всё работало идеально, я копал файл проверял модуль который работает с этим файлом, у меня не получилось то что я хотел и вернул все изменения, сохранил зашел на главную и начались косяки. Я всё бросил пошел спать, начал копать вообще ничего не понимал удалял js скрипты, перезагружал их, ничего не изменялось. И решил я загрузить файл который копал с исходника, при загрузке увидил что они отличаются размерами, но когда новый файл встал размер не изменился, он остался таким каким и был на фтп.
Даже не знаю куда копать, может быть такое что из-за необновления кэша я увидел эти изменения спустя несколько часов или дней? А на самом деле эти глюки уже давно?

13 Hooligan 05.10.2012 19:29

  • Hooligan
  • ТоварисЧЬ!
  • Карма: 31 / 0

Re: Перестали работать js скрипты


Я конечно очень рад за помощь, но я уверен на 100% что копать нужно не там. Просто понимаете, всё работало идеально, я копал файл проверял модуль который работает с этим файлом, у меня не получилось то что я хотел и вернул все изменения, сохранил зашел на главную и начались косяки. Я всё бросил пошел спать, начал копать вообще ничего не понимал удалял js скрипты, перезагружал их, ничего не изменялось. И решил я загрузить файл который копал с исходника, при загрузке увидил что они отличаются размерами, но когда новый файл встал размер не изменился, он остался таким каким и был на фтп.
Даже не знаю куда копать, может быть такое что из-за необновления кэша я увидел эти изменения спустя несколько часов или дней? А на самом деле эти глюки уже давно?

Да, скорее всему виной КЕШ!
удалите старый файл js а уже потом залейте новый или же сравните в них наличие строк!

Уроки JavaScript – не работают события jQuery после AJAX загрузки

Если вы используете AJAX на своем сайте, имейте в виду, что такие события, как клик (click), отправка (submit), наведение (hover), могут не работать, если вы не прикрепите их правильно. В сегодняшней статье мы рассмотрим практическое решение проблемы, когда не срабатывают события в jQuery после динамического изменения страницы (или AJAX).

Описание задачи

Допустим, у нас есть блоки с заголовком и скрытым контентом в теге

. По клику на заголовке, скрытый контент показывается/прячется с помощью функции toggle() :

Потом мы загружаем новые элементы (блоки) без перезагрузки страницы с помощью AJAX. Когда мы перезагружаем страницу – все работает нормально, но если новые элементы подгружаются AJAX’ом, — не работает функция toggle() .

Вариант решения №1

Событие click прикрепляется к существующим элементам после полной загрузки страницы. Ключевое слово здесь – существующим. Когда мы загружаем что-то с помощью AJAX, мы манипулируем DOM. Мы размещаем абсолютно новый элемент, который не существовал при загрузке страницы. Поэтому нам нужно прикрепить это событие после подгрузки нового контента. Если вы используете функцию .load() (которая загружает данные с сервера и помещает возвращенный HTML в соответствующие элементы), вам просто нужно поместить функцию click() в функцию обратного вызова:

Так мы прикрепляем событие click и к новым добавленным элементам.

Если вы используете функцию .ajax() вместо .load() , просто присоедините событие к функции .done() (которая добавляет обработчик, что будет вызываться при обработке отложенного объекта) AJAX вызова.

Вариант решения №2

Что делать, если мы не хотим прикреплять событие каждый раз, когда вызывается AJAX? Для этого есть другое, более «глобальное» решение. Мы можем использовать функцию .on() .

Функция .click() похожа с .on(‘click’) , но здесь есть одна важная часть – при второй функции мы можем делегировать событие. Преимущество делегированных событий заключается в том, что они могут обрабатывать события для элементов-потомков, которые добавляются в документ позднее (например, при AJAX).

Поэтому вместо того, чтобы прикреплять событие click к завершенному AJAX, мы просто добавляем его более «глобально»:

Мы могли бы присоединить обработчик и к тегу , но лучше прикреплять делегированные события как можно ближе к целевым элементам в документе. Нужно избегать чрезмерного использования document или document.body для делегированных событий на больших страницах с большим DOM.

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

В более ранних версиях jQuery вместо .on() использовались функции .live() (устарела с версии jQuery 1.9) или .delegate() (устарела с версии jQuery 3.0).

Выразительный JavaScript: Функции

Содержание

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

Вы уже видели вызовы функций, таких как alert . Функции – это хлеб с маслом программирования на JavaScript. Идея оборачивания куска программы и вызова её как переменной очень востребована. Это инструмент для структурирования больших программ, уменьшения повторений, назначения имён подпрограммам, и изолирование подпрограмм друг от друга.

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

Средний взрослый русскоговорящий человек знает примерно 10000 слов. Редкий язык программирования содержит 10000 встроенных команд. И словарь языка программирования определён чётче, поэтому он менее гибок, чем человеческий. Поэтому нам обычно приходится добавлять в него свои слова, чтобы избежать излишних повторений.

Определение функции

Определение функции – обычное определение переменной, где значение, которое получает переменная, является функцией. Например, следующий код определяет переменную square, которая ссылается на функцию, подсчитывающую квадрат заданного числа:

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

У функции может быть несколько параметров, или вообще их не быть. В следующем примере makeNoise не имеет списка параметров, а у power их целых два:

Некоторые функции возвращают значение, как power и square, другие не возвращают, как makeNoise, которая производит только побочный эффект. Инструкция return определяет значение, возвращаемое функцией. Когда обработка программы доходит до этой инструкции, она сразу же выходит из функции, и возвращает это значение в то место кода, откуда была вызвана функция. return без выражения возвращает значение undefined .

Параметры и область видимости

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

Важное свойство функций в том, что переменные, созданные внутри функции (включая параметры), локальны внутри этой функции. Это означает, что в примере с power переменная result будет создаваться каждый раз при вызове функции, и эти отдельные её инкарнации никак друг с другом не связаны.

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


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

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

Вложенные области видимости

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

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

Функции flat и mountain видят переменную result, потому что они находятся внутри функции, в которой она определена. Но они не могут видеть переменные count друг друга, потому что переменные одной функции находятся вне области видимости другой. А окружение снаружи функции landscape не видит ни одной из переменных, определённых внутри этой функции.

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

Люди, изучавшие другие языки программирования, могут подумать, что любой блок, заключённый в фигурные скобки, создаёт своё локальное окружение. Но в JavaScript область видимости создают только функции. Вы можете использовать отдельно стоящие блоки:

Но something внутри блока – это та же переменная, что и снаружи. Хотя такие блоки и разрешены, имеет смысл использовать их только для команды if и циклов.

Если это кажется вам странным – так кажется не только вам. В версии JavaScript 1.7 появилось ключевое слово let, которое работает как var, но создаёт переменные, локальные для любого данного блока, а не только для функции.

Функции как значения

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

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

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

Объявление функций

Есть более короткая версия выражения “var square = function…”. Ключевое слово function можно использовать в начале инструкции:

Это объявление функции. Инструкция определяет переменную square и присваивает ей заданную функцию. Пока всё ок. Есть только один подводный камень в таком определении.

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

А что будет, если мы поместим объявление функции внутрь условного блока или цикла? Не надо так делать. Исторически разные платформы для запуска JavaScript обрабатывали такие случаи по разному, а текущий стандарт языка запрещает так делать. Если вы хотите, чтобы ваши программы работали последовательно, используйте объявления функций только внутри других функций или основной программы.

Стек вызовов

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

Обрабатывается она примерно так: вызов greet заставляет проход прыгнуть на начало функции. Он вызывает встроенную функцию console.log, которая перехватывает контроль, делает своё дело и возвращает контроль. Потом он доходит до конца greet, и возвращается к месту, откуда его вызвали. Следующая строчка опять вызывает console.log.

Схематично это можно показать так:

Поскольку функция должна вернуться на то место, откуда её вызвали, компьютер должен запомнить контекст, из которого была вызвана функция. В одном случае, console.log должна вернуться обратно в greet. В другом, она возвращается в конец программы.

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

Хранение стека требует места в памяти. Когда стек слишком сильно разрастается, компьютер прекращает выполнение и выдаёт что-то вроде “stack overflow” или “ too much recursion”. Следующий код это демонстрирует – он задаёт компьютеру очень сложный вопрос, который приводит к бесконечным прыжкам между двумя функциями. Точнее, это были бы бесконечные прыжки, если бы у компьютера был бесконечный стек. В реальности стек переполняется.

Необязательные аргументы

Следующий код вполне разрешён и выполняется без проблем:

Официально функция принимает один аргумент. Однако, при таком вызове она не жалуется. Она игнорирует остальные аргументы и показывает «Здрасьте».

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

Минус этого подхода в том, что возможно,- и даже вероятно,- передать функции неправильное количество аргументов, и вам никто на это не пожалуется.

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

В следующей главе мы увидим, как в теле функции можно узнать точное число переданных ей аргументов. Это полезно, т.к. позволяет создавать функцию, принимающую любое количество аргументов. К примеру, console.log использует это свойство, и выводит все переданные ему аргументы:


Замыкания

Возможность использовать вызовы функций как переменные вкупе с тем фактом, что локальные переменные каждый раз при вызове функции создаются заново, приводит нас к интересному вопросу. Что происходит с локальными переменными, когда функция перестаёт работать?

Следующий пример иллюстрирует этот вопрос. В нём объявляется функция wrapValue, которая создаёт локальную переменную. Затем она возвращает функцию, которая читает эту локальную переменную и возвращает её значение.

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

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

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

Отдельная переменная вроде localVariable из примера с wrapValue уже не нужна. Так как параметр – сам по себе локальная переменная.

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

В нашем примере multiplier возвращает замороженный кусок кода, который мы сохраняем в переменной twice. Последняя строка вызывает функцию, заключённую в переменной, в связи с чем активируется сохранённый код (return number * factor;). У него всё ещё есть доступ к переменной factor, которая определялась при вызове multiplier, к тому же у него есть доступ к аргументу, переданному во время разморозки (5) в качестве числового параметра.

Рекурсия

Функция вполне может вызывать сама себя, если она заботится о том, чтобы не переполнить стек. Такая функция называется рекурсивной. Вот пример альтернативной реализации возведения в степень:

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

Однако, у такой реализации есть проблема – в обычной среде JavaScript она раз в 10 медленнее, чем версия с циклом. Проход по циклу выходит дешевле, чем вызов функции.

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

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

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

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

Я заостряю на этом внимание оттого, что слишком много начинающих программистов хватаются за эффективность даже в мелочах. Результат получается больше, сложнее и часто не без ошибок. Такие программы дольше писать, а работают они часто не сильно быстрее.

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

Вот вам загадка: можно получить бесконечное количество чисел, начиная с числа 1, и потом либо добавляя 5, либо умножая на 3. Как нам написать функцию, которая, получив число, пытается найти последовательность таких сложений и умножений, которые приводят к заданному числу? К примеру, число 13 можно получить, сначала умножив 1 на 3, а затем добавив 5 два раза. А число 15 вообще нельзя так получить.

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

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

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

Чтобы лучше понять, как функция достигает нужного эффекта, давайте просмотрим её вызовы, которые происходят в поисках решения для числа 13.

Отступ показывает глубину стека вызовов. В первый раз функция find вызывает сама себя дважды, чтобы проверить решения, начинающиеся с (1 + 5) и (1 * 3). Первый вызов ищет решение, начинающееся с (1 + 5), и при помощи рекурсии проверяет все решения, выдающие число, меньшее или равное требуемому. Не находит, и возвращает null. Тогда-то оператор || и переходит к вызову функции, который исследует вариант (1 * 3). Здесь нас ждёт удача, потому что в третьем рекурсивном вызове мы получаем 13. Этот вызов возвращает строку, и каждый из операторов || по пути передаёт эту строку выше, в результате возвращая решение.

Выращиваем функции

Существует два более-менее естественных способа ввода функций в программу.

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

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

То, насколько сложно вам подобрать имя для функции, показывает, как хорошо вы представляете себе её функциональность. Возьмём пример. Нам нужно написать программу, выводящую два числа, количество коров и куриц на ферме, за которыми идут слова «коров» и «куриц». К числам нужно спереди добавить нули так, чтобы каждое занимало ровно три позиции.

Очевидно, что нам понадобится функция с двумя аргументами. Начинаем кодить.

Если мы добавим к строке .length, мы получим её длину. Получается, что циклы while добавляют нули спереди к числам, пока не получат строчку в 3 символа.

Готово! Но только мы собрались отправить фермеру код (вместе с изрядным чеком, разумеется), он звонит и говорит нам, что у него в хозяйстве появились свиньи, и не могли бы мы добавить в программу вывод количества свиней?

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


Работает! Но название printZeroPaddedWithLabel немного странное. Оно объединяет три вещи – вывод, добавление нулей и метку – в одну функцию. Вместо того, чтобы вставлять в функцию весь повторяющийся фрагмент, давайте выделим одну концепцию:

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

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

Хорошее правило – добавляйте только ту функциональность, которая вам точно пригодится. Иногда появляется искушение создавать фреймворки общего назначения для каждой небольшой потребности. Сопротивляйтесь ему. Вы никогда не закончите работу, а просто напишете кучу кода, который никто не будет использовать.

Функции и побочные эффекты

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

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

Чистая функция – особый вид функции, возвращающей значения, которая не только не имеет побочных эффектов, но и не зависит от побочных эффектов остального кода – к примеру, не работает с глобальными переменными, которые могут быть случайно изменены где-то ещё. Чистая функция, будучи вызванной с одними и теми же аргументами, возвращает один и тот же результат (и больше ничего не делает) – что довольно приятно. С ней просто работать. Вызов такой функции можно мысленно заменять результатом её работы, без изменения смысла кода. Когда вы хотите проверить такую функцию, вы можете просто вызвать её, и быть уверенным, что если она работает в данном контексте, она будет работать в любом. Не такие чистые функции могут возвращать разные результаты в зависимости от многих факторов, и иметь побочные эффекты, которые сложно проверять и учитывать.

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

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

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

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

Упражнения

Минимум

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

Рекурсия

Мы видели, что оператор % (остаток от деления) может использоваться для определения того, чётное ли число ( % 2). А вот ещё один способ определения:

Ноль чётный.
Единица нечётная.
У любого числа N чётность такая же, как у N-2.

Напишите рекурсивную функцию isEven согласно этим правилам. Она должна принимать число и возвращать булевское значение.

Потестируйте её на 50 и 75. Попробуйте задать ей -1. Почему она ведёт себя таким образом? Можно ли её как-то исправить?

Test it on 50 and 75. See how it behaves on -1. Why? Can you think of a way to fix this?

Считаем бобы.

Символ номер N строки можно получить, добавив к ней .charAt(N) ( “строчка”.charAt(5) ) – схожим образом с получением длины строки при помощи .length. Возвращаемое значение будет строковым, состоящим из одного символа (к примеру, “к”). У первого символа строки позиция 0, что означает, что у последнего символа позиция будет string.length – 1. Другими словами, у строки из двух символов длина 2, а позиции её символов будут 0 и 1.

Напишите функцию countBs, которая принимает строку в качестве аргумента, и возвращает количество символов “B”, содержащихся в строке.

Затем напишите функцию countChar, которая работает примерно как countBs, только принимает второй параметр — символ, который мы будем искать в строке (вместо того, чтобы просто считать количество символов “B”). Для этого переделайте функцию countBs.

#js — Не работает функция на JS

Вот возможное решение: Вместо change() мы добавили к textbox onblur() и оно записывает до Postback в куки. Огромное спасибо за помощь!! Последний ответ натолкнул на это решение.

  • Изменено Andrey_ua 25 июля 2012 г. 7:06
  • Помечено в качестве ответа Yatajga Editor 25 июля 2012 г. 7:10

Все ответы

А у Вас значение свойства

случайно в true не установлено? Если нет, тогда подробней, причин может быть много, ограничение домена и т.п.

У нас есть такой код:

С начала етот код был привязан к кнопке(input button click) но теперь надо его с Code-behind вызвать.

Как я не люблю этот уровень абстракций WebForms. Из-за куска скрипта, столько возни, другое дело MVC. Теперь уже понятно. Это не вызов, а регистрация. Вы регистрируете скрипт на странице, чтобы сервер знал что этото код оно сгенерировал. А вызов, это когда данны код отработает на клиенте. Используйте JavaScript отладчик, например мой любимый Firebug, установите точку прерывания(breakpoint), и посмотрите что там творится, выполняется ли код и записывается значение в объект document.cookie.

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

На сервере(HttpContext.Current.Request.Cookies[«Image1»].Value) . Код работает нормально когда находится в функции которая вызывается кнопкой но не работает когда функция вызывается в- RegisterStartupScript.

То что должно работать ето такой же функционал только на Textbox. На Textbox1 есть TextChanged где и стоит:

То что должно происходить ето что когда есть изменение в TextBox, создается объект который можно двигать. Проблем была в том что он возвращался на оригинальное место.

Расскажу о задаче которую необходимо решить.

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

#js — Не работает функция на JS

98 просмотра

1 ответ

102 Репутация автора

У меня есть страница php, которая показывает таблицу записей, и в одном из столбцов у меня есть кнопка «Печать»:

У меня есть файл JavaScript, добавленный в php:

Функция в logic.js:

Другие кнопки на странице работают, вызывая соответствующую функцию js по ID, но ничего не происходит, когда я нажимаю «Печать». Есть идеи?

Изменить searchEntries.html:

searchentries.php

logic.js

Редактировать # 2 — logic.js

Edit # 3 Мне нужно только значение из первого столбца в таблице, чтобы передать в файл php, но так как это скрытый столбец, я не могу использовать .text () следующим образом:

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

Ответы (1)

1 плюс

407 Репутация автора

Вот минимальная попытка того, чего вы, возможно, пытаетесь достичь:

Использование PHP для генерации кнопки:

Использование простого HTML для генерации кнопки:

Можете ли вы проверить код по приведенному фрагменту?

Обновление 1: После того, как ОП опубликовал больше деталей в комментариях.

Если ввод HTML добавляется динамически, вызовите функцию addClickHandlers () с идентификатором ввода HTML, с которым вы хотите связать событие click. Посмотрите на приведенный ниже фрагмент для примера.

Обновление 2: после ОП выложено больше подробностей в комментариях и оригинальном посте.

JavaScript — функция eval () не работает

Я пытаюсь конвертировать JSON-строку из моего .php-файла, используя функцию eval (), но это не работает. консоль браузера говорит
SyntaxError: ожидаемое выражение, получил ‘ $.getJSON() вместо eval() или указав json в качестве параметра в $.get() и это все хорошие предложения. Но они не причина, по которой это не работает.

Просто вам не хватает точки с запятой в вашем var go = . определение функции после закрывающей скобки возле дна.

Другие решения

код теперь исправлен! лол, я не знаю почему, но я просто удалил закомментированный HTML-код из моего .php-кода … как, черт возьми, это влияет на мой код в первую очередь ?? это просто комментарий …: /

Почему .он ( «нагрузка», функция) не работает на JS шаблонах?

December 2020

414 раз

Я впрыснуть mustachejs шаблонов в моей странице, то у меня есть функция, чтобы огнь по этим шаблонам.

JS такие:

Может кто-то объяснить, почему первый выходит из строя.

1 ответы

The element doesn’t (directly) load external content, so it doesn’t have a load event.

Use window instead (wrap the window object itself with jQuery, don’t try to select a element).

Событие onclick в javascript и jquery на примерах

Такое простое событие, как onclick в javascript, может быть вызвано несколькими способами и скрыает некоторые тонкости. Событие происходит при клике по элементу левой кнопкой мыши. Стоит заметить, что при клике происходит так же ещё два события, а именно нажатие на кнопку мыши и её отжатие.

Все примеры будем рассматривать на теге «a» (ссылку). Пусть это не смущает, с другими тегами будет работать аналогичным образом.

Самый простой способ повесить событие onclick, это прописать его непосредственно в html теге:

В примере при нажатии на ссылку появляется всплывающее окно с сообщением. Дополнительно к действию мы прописали «return false;». Это требуется чтобы предотвратить переход по ссылке после срабатывания события «onclick». В других элементах (где нет аттрибута href) это можно опустить.

Рассмотренный вариант можно использовать если событие содержит мало кода. Иначе, следует обратить внимание на другие способы.

Выносим код события onclick в javascript-функцию

Следующий способ хорош тем, что мы отделяем javascript-код от html тегов. В теге прописываем название функции, а саму функцию выносим в отдельный блок:

Но и здесь всё не идеально. Что делать, если событие требуется повесить на все ссылыки сайта, а их сотни? Кажется что это трудно, а на деле — меньше десяти строк кода. Задача решается с помощью селекторов. В примере опять будем производить действия с тегом «a», но ничего не мешает использовать вместо ссылки «img» или «div».

Вешаем onclick на элемент из javascript-кода

Рассмотим еще один способ, на мой взгляд, самый практичный и надежный. Хорош он тем, что событие можно повесить на множество элементов. Для этого требуется выбрать при помощи javascript-селекторов элементы, к которым требуется применить событие onclick.

Выбору элементов по селекторам можно посвятить отдельную тему, могу сказать только то, что согласно новой спецификации HTML5, их выбор стал прост и в javascript. Если Вы знакомы с jquery или CSS, то выбрать нужные элементы для Вас не составит труда. Например, так просто можно выбрать все элементы с классом «link» и повесить на них нужное действие:

Применяем jQuery

Если в проекте используется библиотека jQuery, то можно ещё упростить код. Рассмотрим два самых распространенных способа:

И ещё один вариант, который идентичен предыдущему.

С обработчиком «on()» лучше ознакомиться отдельно, так как он несет в себе много полезного функционала. Например, возможность указать через пробел несколько событий к которым будет применяться действие, делегировать события на дочерние элементы, а так же он полезен если необходимо повесить событие на динамически добавляемые элементы, которых изначально нет на странице.

Цукерберг рекомендует:  Events - IoT хакатон и Ростелеком!
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих