Dlaczego mój JavaScript nie działa w JSFiddle?

114

Nie mogę dowiedzieć się, jaki jest problem z tym JSFiddle .

HTML:

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

JavaScript:

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

A kiedy klikam na przycisk - nic się nie stało. Konsola wyświetla komunikat „test niezdefiniowany”

Przeczytałem dokumentację JSFiddle - tam jest napisane, że kod JS jest dodawany, <head>a kod HTML jest dodawany do <body>(więc ten kod JS jest starszy niż html i powinien działać).

Larry Cinnabar
źródło
Usunięcie nawiasów zadziałałoby również w normalnych okolicznościach, które nie są skrzypcami, chociaż zdecydowanie dobrą radą jest oddzielenie js od HTML tak bardzo, jak to możliwe. Pozwalam sobie tylko na styl = "display: none" CSS inline no-no.
Adrian Bartholomew,

Odpowiedzi:

60

Funkcja jest definiowana wewnątrz nośnika ładunku i dlatego znajduje się w innym zakresie. Jak @ellisbben zauważa w komentarzach, możesz to naprawić, jawnie definiując to w windowobiekcie. Jeszcze lepiej, zmień to, aby dyskretnie zastosować procedurę obsługi do obiektu: http://jsfiddle.net/pUeue/

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

Zwróć uwagę, że zastosowanie procedury obsługi w ten sposób, zamiast wbudowanego, zapewnia czysty kod HTML. Używam jQuery, ale możesz to zrobić z frameworkiem lub bez niego lub używając innego frameworka, jeśli chcesz.

tvanfosson
źródło
@Innuendo - jsFiddle używa oddzielnych ramek dla kodu / html / arkuszy stylów. musiałbyś odwołać się do ramki w wywołaniu funkcji, ale nie ma na to łatwego sposobu, ponieważ ramka nie ma nazwy. To naprawdę problem ze względu na sposób działania jsfiddle, ale nadal dobrym pomysłem jest oddzielenie javascript.
tvanfosson
5
@ tvanfosson - Twoje rozwiązanie działa, ale jsfiddle nie używa oddzielnych ramek do pokazania wyniku; zobacz jsfiddle.net/Yazpj/show . Przyczyną, dla której początkowo nie działało, jest to, że testzostało zdefiniowane wewnątrz onLoadfunkcji; używanie window.test = function(){/*...*/}sprawia, że ​​działa idealnie.
ellisbben
@ellisbben - jeśli używam Firebuga do inspekcji DOM, każdy z 4 oddzielnych paneli istnieje w osobnym iframe.
tvanfosson
1
Tak, ale jeśli przeanalizujesz pojedynczą ramkę iframe użytą do pokazania przykładu, zobaczysz, że umieszcza ona cały kod na jednej stronie, która nie używa ramek, dlatego te ramki nie mogą zepsuć przykładu. Dołącz showdo dowolnego adresu URL jsfiddle, aby zobaczyć, o czym mówię: jsfiddle.net/Yazpj/show
ellisbben
100

Jeśli nie określisz ustawienia zawijania, domyślnie jest to „onLoad”. Powoduje to zawinięcie całego kodu JavaScript w funkcję uruchamianą po załadowaniu wyniku. Wszystkie zmienne są lokalne dla tej funkcji, dlatego nie są dostępne w zasięgu globalnym.

Zmień ustawienie zawijania na „bez zawijania” i zadziała:

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

Zmieniłem framework na „Brak biblioteki”, ponieważ nie używasz żadnej.

zalun
źródło
22

Jest inny sposób, zadeklaruj swoją funkcję w zmiennej takiej jak ta:

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

jsFiddle


Detale

EDYTUJ (na podstawie komentarzy @nnnnnn)

@nnnnnn:

dlaczego powiedzenie test =(bez var) miałoby to naprawić?

Kiedy definiujesz taką funkcję:

var test = function(){};

Funkcja jest definiowana lokalnie, ale kiedy definiujesz funkcję bez var:

test = function(){};

testjest zdefiniowana na windowobiekcie, który jest w zakresie najwyższego poziomu.

dlaczego to działa?

Jak @zalun powiedz:

Jeśli nie określisz ustawienia zawijania, domyślnie jest to „onLoad”. Powoduje to zawinięcie całego kodu JavaScript w funkcję uruchamianą po załadowaniu wyniku. Wszystkie zmienne są lokalne dla tej funkcji, dlatego nie są dostępne w zasięgu globalnym.

Ale jeśli używasz tej składni:

test = function(){};

Masz dostęp do funkcji, testponieważ jest zdefiniowana globalnie


Bibliografia :

R3tep
źródło
2
To naprawdę najprostsze podejście - po prostu testujesz niewielki fragment kodu w JSFiddle.
DOK
Ale dlaczego to działa? Podane przez Ciebie łącze „Więcej informacji” nie wyjaśnia, że ​​problem jest związany z zakresem ani dlaczego powiedzenie test = (bez var) miałoby go naprawić.
nnnnnn
@ R3tep dobrze, twój pierwszy link, który jest: alert jsfiddle.net/R3tep/Yazpj/1406 nic dla mnie nie robi. Jestem na chrome.
środa,
@ R3tep tak, działa z console.log. Opublikuję pytanie na SO, ponieważ uważam, że fakt, że nie mam pola ostrzegawczego, jest powiązany z innym problemem z ramkami iframe.
środa,
1
@ R3tep Myślę, że mnie źle zrozumiałeś, ale nie jestem pewien. Twój kod jest / był dobry. Występuje problem z kodowaniem JSFiddle (brak wartości w atrybucie piaskownicy elementu iframe, którego używają do wyświetlenia wyniku). To sprawia, że ​​nie będzie działać na niektórych wersjach chrome. Wysłałem zgłoszenie problemu na ich github. Byłem nim tak bardzo zainteresowany, ponieważ myślałem, że problem, który mam na mojej stronie, jest taki sam, ale nie. Twoje zdrowie.
Ced,
3

Zmień ustawienie zawijania w panelu Struktury i rozszerzenia na „Bez zawijania <body>

Academia
źródło
-1

Nie ma problemu z Twoim kodem, po prostu wybierz rozszerzenie onLoad () z prawej strony.

Omjjh
źródło
-1
<script> 
function test(){
 alert("test");   
}
</script>

<input type="button" value="test" onclick="test()">
Muslim Munir
źródło
-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");
}
Ivan
źródło