Почему мой JavaScript не работает в JSFiddle?

114

Я не могу понять, в чем проблема с этим JSFiddle .

HTML:

<input type="button" value="test" onclick="test()">

JavaScript:

function test(){alert("test");}

А когда нажимаю на кнопку - ничего не произошло. На консоли написано «тест не определен»

Я читал документацию JSFiddle - там написано, что JS-код добавлен <head>и HTML-код добавлен <body>(так что этот JS-код раньше, чем html, и должен работать).

Ларри Синнабар
источник
Удаление круглых скобок также будет работать при обычных обстоятельствах, не связанных со скрипкой, хотя это определенно хороший совет - как можно больше отделить js от HTML. Я разрешаю себе только style = "display: none" встроенный CSS no-no.
Адриан Варфоломей,

Ответы:

60

Функция определяется внутри обработчика нагрузки и, следовательно, находится в другой области видимости. Как отмечает @ellisbben в комментариях, вы можете исправить это, явно указав это в windowобъекте. А еще лучше изменить его, чтобы обработчик ненавязчиво применялся к объекту: http://jsfiddle.net/pUeue/

$('input[type=button]').click( function() {
   alert("test");   
});

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

tvanfosson
источник
@Innuendo - jsFiddle использует отдельные фреймы для кода / html / таблиц стилей. вам нужно будет сослаться на фрейм в вызове функции, но на самом деле нет простого способа сделать это, поскольку у фрейма нет имени. Это действительно проблема из-за того, как работает jsfiddle, но все же неплохо держать ваш javascript полностью отдельным.
tvanfosson
5
@ tvanfosson - ваше решение работает, но jsfiddle не использует отдельные фреймы для отображения результата; см. jsfiddle.net/Yazpj/show . Причина, по которой он изначально не работал, заключается в том, что он testбыл определен внутри onLoadфункции; использование window.test = function(){/*...*/}заставляет его работать отлично.
ellisbben 02
@ellisbben - если я использую Firebug для проверки DOM, каждая из 4 отдельных панелей существует в отдельном iframe.
tvanfosson 02
1
Да, но если вы изучите единственный iframe, используемый для демонстрации примера, вы увидите, что он помещает весь код на одну страницу, которая не использует фреймы, поэтому эти фреймы не могут нарушить ваш пример. Добавьте showк любому URL-адресу jsfiddle, чтобы увидеть, о чем я говорю: jsfiddle.net/Yazpj/show
ellisbben 02
100

Если вы не укажете настройку обтекания, по умолчанию будет установлено значение «onLoad». В результате весь JavaScript включается в функцию, запускаемую после загрузки результата. Все переменные являются локальными для этой функции, поэтому недоступны в глобальной области видимости.

Измените настройку переноса на «без переноса», и он будет работать:

http://jsfiddle.net/zalun/Yazpj/1/

Я переключил фреймворк на «Без библиотеки», так как вы их не используете.

Залун
источник
22

Есть другой способ объявить вашу функцию в переменной, например:

test = function() {
  alert("test");
}

jsFiddle


подробности

ИЗМЕНИТЬ (на основе комментариев @nnnnnn)

@nnnnnn:

почему высказывание test =(без var) исправит это?

Когда вы определяете такую ​​функцию:

var test = function(){};

Функция определяется локально, но когда вы определяете свою функцию без var:

test = function(){};

testопределяется на windowобъекте, который находится в области действия верхнего уровня.

почему это работает?

Как сказал @zalun:

Если вы не укажете настройку обтекания, по умолчанию будет установлено значение «onLoad». В результате весь JavaScript включается в функцию, запускаемую после загрузки результата. Все переменные являются локальными для этой функции, поэтому недоступны в глобальной области видимости.

Но если вы используете этот синтаксис:

test = function(){};

У вас есть доступ к функции, testпотому что она определена глобально


Ссылки :

R3tep
источник
2
Это действительно самый простой подход - вы просто тестируете небольшой фрагмент кода в JSFiddle.
DOK
Но почему это работает? Ссылка «Дополнительная информация», которую вы предоставили, не объясняет, что проблема связана с областью действия или почему указание test = (без var) исправит ее.
nnnnnn
@ R3tep хорошо, ваша первая ссылка: jsfiddle.net/R3tep/Yazpj/1406 alert ничего не делает для меня. Я на хроме.
Ced
@ R3tep да, он работает с console.log. Я опубликую вопрос о SO, потому что считаю, что тот факт, что у меня нет окна предупреждений, связан с другой проблемой с iframe.
Ced
1
@ R3tep Я думаю, вы меня неправильно поняли, но я не уверен. Ваш код хорош. Возникла проблема с кодированием JSFiddle (отсутствует значение в атрибуте песочницы iframe, который они используют для отображения результата). Это делает его таким, что он не будет работать с некоторыми версиями Chrome. Я отправил отчет о проблеме на их гитхаб. Я был так сильно заинтересован в этом, потому что думал, что проблема, с которой я столкнулся на моем веб-сайте, такая же, но нет. Приветствия.
Ced
3

Измените настройку переноса на панели Frameworks & Extensions на "Без переноса <body>"

академия
источник
-1

С вашим кодом проблем нет, просто выберите расширение onLoad () справа.

Omjjh
источник
-1
<script> 
function test(){
 alert("test");   
}
</script>

<input type="button" value="test" onclick="test()">
Муслим Мунир
источник
-3
Select OnDomready

HTML:

<input id="dButton" type="button" value="test"/>

JavaScript:

addEventListener('load', init, false);

function init()
{
  oInput = document.getElementById('dButton');
  oInput.onclick = test;
}

function test(){
  alert("test");
}
Иван
источник