Por que meu JavaScript não está funcionando no JSFiddle?

114

Não consigo descobrir qual é o problema com este JSFiddle .

HTML:

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

JavaScript:

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

E quando clico no botão - nada aconteceu. O console diz "teste não definido"

Eu li a documentação do JSFiddle - lá está escrito que o código JS é adicionado <head>e o código HTML é adicionado <body>(portanto, esse código JS é anterior ao html e deve funcionar).

Larry Cinnabar
fonte
Remover os parênteses também funcionaria em circunstâncias normais que não sejam violentas, embora seja definitivamente um bom conselho separar js de HTML o máximo possível. Eu só me permito o estilo = "display: none" CSS inline no-no.
Adrian Bartholomew

Respostas:

60

A função está sendo definida dentro de um manipulador de carga e, portanto, está em um escopo diferente. Como @ellisbben observa nos comentários, você pode corrigir isso definindo-o explicitamente no windowobjeto. Melhor ainda, altere-o para aplicar o manipulador ao objeto discretamente: http://jsfiddle.net/pUeue/

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

Observe que aplicar o manipulador dessa maneira, em vez de embutir, mantém seu HTML limpo. Estou usando jQuery, mas você pode fazer isso com ou sem uma estrutura ou usando uma estrutura diferente, se quiser.

Tvanfosson
fonte
@Innuendo - jsFiddle usa frames separados para código / html / folhas de estilo. você precisaria fazer referência ao quadro na chamada de função, mas não há realmente uma maneira fácil de fazer isso, pois o quadro não tem um nome. É realmente um problema devido à maneira como o jsfiddle funciona, mas ainda é uma boa ideia manter seu javascript completamente separado.
tvanfosson
5
@ tvanfosson- sua solução funciona, mas jsfiddle não usa frames separados para mostrar o resultado; consulte jsfiddle.net/Yazpj/show . O motivo pelo qual não funcionou inicialmente é que testfoi definido dentro de uma onLoadfunção; usar window.test = function(){/*...*/}faz com que funcione perfeitamente bem.
ellisbben,
@ellisbben - se eu usar o Firebug para inspecionar o DOM, cada um dos 4 painéis separados existe em um iframe separado.
tvanfosson,
1
Sim, mas se você examinar o iframe único usado para mostrar o exemplo, verá que ele coloca todo o código em uma única página que não usa quadros, portanto, esses quadros não podem quebrar seu exemplo. Anexe showa qualquer URL do jsfiddle para ver do que estou falando: jsfiddle.net/Yazpj/show
ellisbben
100

Se você não especificar a configuração de wrap, o padrão é "onLoad". Isso faz com que todo o JavaScript seja agrupado em uma função executada após o carregamento do resultado. Todas as variáveis ​​são locais para esta função, portanto, indisponíveis no escopo global.

Altere a configuração de embalagem para "sem embalagem" e funcionará:

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

Mudei a estrutura para "Sem biblioteca" porque você não usa nenhuma.

zalun
fonte
22

Há outra maneira de declarar sua função em uma variável como esta:

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

jsFiddle


Detalhes

EDIT (com base nos comentários de @nnnnnn)

@nnnnnn:

por que dizer test =(sem var) resolveria isso?

Quando você define uma função como esta:

var test = function(){};

A função é definida localmente, mas quando você define sua função sem var:

test = function(){};

testé definido no windowobjeto que está no escopo de nível superior.

porque isso funciona?

Como @zalun, diga:

Se você não especificar a configuração de wrap, o padrão é "onLoad". Isso faz com que todo o JavaScript seja agrupado em uma função executada após o carregamento do resultado. Todas as variáveis ​​são locais para esta função, portanto, indisponíveis no escopo global.

Mas se você usar esta sintaxe:

test = function(){};

Você tem acesso à função testporque ela é definida globalmente


Referências :

R3tep
fonte
2
Esta é realmente a abordagem mais simples: você está apenas testando um pequeno trecho de código no JSFiddle.
DOK
Mas por que isso funciona? O link "Mais informações" fornecido não explica se o problema está relacionado ao escopo ou por que dizer test = (sem var) resolveria o problema.
nnnnnn de
@ R3tep bem, seu primeiro link que é: jsfiddle.net/R3tep/Yazpj/1406 alert não faz nada para mim. Estou no cromo.
Ced,
@ R3tep sim, funciona com console.log. Vou postar uma pergunta no SO porque acredito que o fato de não ter uma caixa de alerta está relacionado a outro problema que tenho com iframes.
Ced,
1
@ R3tep Acho que você me entendeu mal, mas não tenho certeza. Seu código é / estava bom. Há um problema com a forma como o JSFiddle é codificado (valor ausente no atributo sandbox do iframe que estão usando para exibir o resultado). Isso faz com que não funcione em alguma versão do Chrome. Enviei um relatório de problema em seu github. Eu estava muito interessado nele porque pensei que o problema que estava tendo no meu site era o mesmo, mas não. Felicidades.
Ced,
3

Altere a configuração de agrupamento no painel Estruturas e extensões para "Sem agrupamento <body>"

Academia
fonte
-1

Não há problema com seu código. Basta escolher a extensão onLoad () do lado direito.

Omjjh
fonte
-1
<script> 
function test(){
 alert("test");   
}
</script>

<input type="button" value="test" onclick="test()">
Munir muçulmano
fonte
-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
fonte