Diferença entre setTimeout com e sem aspas e parênteses

240

Estou aprendendo JavaScript e aprendi recentemente sobre eventos de sincronização de JavaScript. Quando soube setTimeoutda W3Schools , notei uma figura estranha na qual não encontrei antes. Eles estão usando aspas duplas e depois chamam a função

Exemplo:

setTimeout("alertMsg()", 3000);

Eu sei que aspas duplas e simples em JavaScript significa uma string.

Também vi que posso fazer o mesmo assim:

setTimeout(alertMsg, 3000);

Com os parênteses está se referindo, sem os parênteses é copiado. Quando estou usando aspas e parênteses, está ficando louco.

Ficarei feliz se alguém puder me explicar a diferença entre essas três maneiras de usar setTimeout:

Com os parênteses:

setTimeout("alertMsg()", 3000);

Sem as aspas e os parênteses:

setTimeout(alertMsg, 3000);

E o terceiro está usando apenas aspas:

setTimeout("alertMsg", 3000);

NB: Uma melhor fonte de setTimeoutreferência seria MDN .

user1316123
fonte
5
@ Jeffffrey que o site w3fools não diz que o conteúdo está errado, apenas que pode estar desatualizado e com falta de algumas das novidades. Deve ser bom usar como referência para (ou aprender) o material principal. Entendo as pessoas frustradas pela maneira como tentam parecer que fazem parte do w3, mas isso não prejudica o conteúdo. É bem organizado e fácil de ler com exemplos claros, perfeito para noobs.
Matthew
14
@ Matthew "Mas sentimos que o W3Schools está prejudicando a comunidade com informações imprecisas." - dentro das três primeiras linhas.
Shoe
1
@Jefffrey, sim, eu vi isso, mas lá embaixo, onde eles explicam o que não gostam, na seção "W3Schools is trouble", nenhuma das três razões que eles dão têm algo a ver com informações imprecisas. Eles não têm um único exemplo de algo que esteja realmente "errado". Suas queixas são de que eles não dizem explicitamente que não são afiliados ao w3, cobram por certificações não reconhecidas e não atualizam rapidamente com o novo conteúdo (por exemplo, html 5).
Matthew
10
@Mathew, informações desatualizadas, em linguagens delicadas como Javascript, SQL ou PHP, é o que guia massas de programadores aspirantes a mysql_seguir tecnologias antigas e potencialmente perigosas (como a extensão do PHP) das quais o fluxo de perguntas SO é apenas um exemplo. No IIRC, também houve alguns erros sutis na seção SQL, mas já faz quase um ano desde a última vez que visitei o site e muitos deles podem ser corrigidos. E mesmo se tudo acima fosse perfeito, eu ainda não promoveria um site que tentasse enganar as pessoas com a fraude de seu certificado.
Shoe
4
Certificações obscuras à parte, é um recurso de referência decente e é contraproducente para todo o SO denunciar as denúncias.
WORC

Respostas:

382

Usando setInterval ousetTimeout

Você deve passar uma referência a uma função como o primeiro argumento para setTimeout or setInterval. Esta referência pode estar na forma de:

  • Uma função anônima

    setTimeout(function(){/* Look mah! No name! */},2000);
  • Um nome de uma função existente

    function foo(){...}
    
    setTimeout(foo, 2000);
  • Uma variável que aponta para uma função existente

    var foo = function(){...};
    
    setTimeout(foo, 2000);

    Observe que eu defino "variável em uma função" separadamente de "nome da função". Não é aparente que variáveis ​​e nomes de funções ocupem o mesmo espaço para nome e possam se opor.

Passando argumentos

Para chamar uma função e passar parâmetros, você pode chamar a função dentro do retorno de chamada atribuído ao timer:

setTimeout(function(){
  foo(arg1, arg2, ...argN);
}, 1000);

Existe outro método para passar argumentos para o manipulador, no entanto, ele não é compatível com vários navegadores .

setTimeout(foo, 2000, arg1, arg2, ...argN);

Contexto de retorno de chamada

Por padrão, o contexto do retorno de chamada (o valor de thisdentro da função chamada pelo timer) quando executado é o objeto global window. Se você quiser mudar, use bind.

setTimeout(function(){
  this === YOUR_CONTEXT; // true
}.bind(YOUR_CONTEXT), 2000);

Segurança

Embora seja possível, você não deve passar uma string para setTimeoutou setInterval. Passar uma string torna setTimeout()ou setInterval()usa uma funcionalidade semelhante à eval()que executa strings como scripts , possibilitando a execução arbitrária e potencialmente prejudicial de scripts.

Joseph
fonte
Eu aprendi que quando você está usando apenas o nome da função, a função é copiada. Por que você está dizendo no seu primeiro exemplo que setTumeout foo (function) passa a referência que a função que eu inclinei é copiada. e você pode me dizer mais sobre a avaliação, por favor.
usar o seguinte comando
41
@ user1316123 as funções nunca são copiadas. mesmo com objetos e matrizes. eles são passados ​​por referência . você deve parar de ler w3schools. eles estão fazendo mais mal do que bem
Joseph
4
As funções @JosephtheDreamer são objetos. "Um nome de função" e "Uma variável que se refere a uma função" é a mesma coisa. Além disso, você pode passar parâmetros para setTimeout diretamente (não é necessário agrupar um lambda para ele (embora, como você disse - navegadores mais recentes). Além disso, o problema não é permitir que os usuários executem scripts (eles sempre podem fazer isso de qualquer maneira), é de aceitar a entrada de outros usuários e funcionando que como script o usuário-se sempre pode apenas abrir o console e executar arbitrária JavaScript..
Benjamin Gruenbaum
@BenjaminGruenbaum Eu estava prestes a fazer um comentário quase idêntico à sua segunda frase. Laugh :)
ErikE
2
Não sabia que você precisava usar uma função para que o setTimeout funcionasse corretamente. Obrigado por esclarecer isso.
Matt Dell
3

Eu acho que a função setTimeout que você escreve não está sendo executada. se você usa o jquery, pode fazê-lo funcionar corretamente, fazendo o seguinte:

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });
Acil Az
fonte
i thinkink Assim como você, mas o link w3schools.com/js/js_timing.asp dizendo somting outra coisa
user1316123
se eu entendi corretamente quando uso Brackets, posso me referir apenas à função que contém o método setTimeout, porque a função Disponível nos colchetes apenas no escopo local?
precisa saber é o seguinte
2

Concordo totalmente com Joseph.

Aqui está um violino para testar isso: http://jsfiddle.net/nicocube/63s2s/

No contexto do violino, o argumento string não funciona, na minha opinião, porque a função não está definida no escopo global.

Nicocube
fonte
w3schools.com/js/js_timing.asp se você pode entrar no link favor e veja becouse Joseph diz que seu perigoso, mas se você entrar no link seu trabalho
user1316123
caras agradar olhada nisso: quirksmode.org/js/this.html este link diz que um func pode ser copiado
user1316123
Sim, pode, porque a função é objeto em JS. O problema com a avaliação é que ela avaliará no contexto global e não conseguirá o contexto local que ocorre com um violino.
Nicocube
você pode explicar em algumas palavras sobre eval, por favor.
precisa saber é o seguinte
Algumas boas explicações: javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval
Nicocube
1

O que acontece na realidade no caso de você passar a string como o primeiro parâmetro da função

setTimeout ( 'string', number)

é o valor do primeiro parâmetro avaliado quando é hora de executar (após numbermilissegundos passados). Basicamente, é igual a

setTimeout ( eval('string'), number)

Isto é

uma sintaxe alternativa que permite incluir uma string em vez de uma função, que é compilada e executada quando o timer expirar. Essa sintaxe não é recomendada pelos mesmos motivos que tornam o uso de eval () um risco à segurança.

Portanto, as amostras que você se refere não são boas e podem ser fornecidas em diferentes contextos ou apenas erros de digitação.

Se você chamar assim setTimeout(something, number), o primeiro parâmetro não será uma string, mas um ponteiro para algo chamado something. E novamente se somethingfor string - então será avaliado. Mas se for função, a função será executada. amostra jsbin

Vitaliy Markitanov
fonte
0
    ##If i want to wait for some response from server or any action we use setTimeOut.

    functionOne =function(){
    console.info("First");

    setTimeout(()=>{
    console.info("After timeOut 1");
    },5000);
    console.info("only setTimeOut() inside code waiting..");
    }

    functionTwo =function(){
    console.info("second");
    }
    functionOne();
    functionTwo();

## So here console.info("After timeOut 1"); will be executed after time elapsed.
Output:
******************************************************************************* 
First
only setTimeOut() inside code waiting..
second
undefined
After timeOut 1  // executed after time elapsed.
Avinash Khadsan
fonte
-1

Com os parênteses:

setTimeout("alertMsg()", 3000); // It work, here it treat as a function

Sem as aspas e os parênteses:

setTimeout(alertMsg, 3000); // It also work, here it treat as a function

E o terceiro está usando apenas aspas:

setTimeout("alertMsg", 3000); // It not work, here it treat as a string

function alertMsg1() {
        alert("message 1");
    }
    function alertMsg2() {
        alert("message 2");
    }
    function alertMsg3() {
        alert("message 3");
    }
    function alertMsg4() {
        alert("message 4");
    }

    // this work after 2 second
    setTimeout(alertMsg1, 2000);

    // This work immediately
    setTimeout(alertMsg2(), 4000);

    // this fail
    setTimeout('alertMsg3', 6000);

    // this work after 8second
    setTimeout('alertMsg4()', 8000);

No exemplo acima, a primeira função alertMsg2 () chama imediatamente (damos o tempo limite 4S, mas não incomoda) depois disso alertMsg1 () (uma espera de tempo de 2 segundos) e alertMsg4 () (uma espera de 8 segundos) mas o alertMsg3 () não está funcionando porque o colocamos entre aspas sem partes, portanto é tratado como uma string.

Srikrushna
fonte
Demonstra os cenários sobre os quais o interlocutor pergunta, mas na verdade não responde à pergunta. Não vejo o que isso acrescenta nas respostas existentes de 6 anos .
Stephen P