¿Cuál es la diferencia entre los diferentes métodos de poner código JavaScript en un?


He visto los siguientes métodos para poner código JavaScript en una etiqueta <a>:

function DoSomething() { ... return false; }
  1. <a href="javascript:;" onClick="return DoSomething();">link</a>
  2. <a href="javascript:DoSomething();">link</a>
  3. <a href="javascript:void(0);" onClick="return DoSomething();">link</a>
  4. <a href="#" onClick="return DoSomething();">link</a>

Entiendo la idea de intentar poner una URL válida en lugar de solo código JavaScript, en caso de que el usuario no tenga JavaScript habilitado. Pero para el propósito de esta discusión, necesito asumir que JavaScript está habilitado (no pueden iniciar sesión sin él).

Personalmente me gusta la opción 2, ya que le permite ver lo que se va a ejecutar–especialmente útil cuando depuración donde hay parámetros que se pasan a la función. Lo he usado bastante y no he encontrado problemas con el navegador.

He leído que la gente recomienda 4, porque le da al usuario un enlace real para seguir, pero en realidad, # no es "real". No irá a ninguna parte.

¿Hay uno que no es compatible o es realmente malo, cuando sabes que el usuario tiene JavaScript habilitado?

Pregunta relacionada: Href para JavaScript enlaces: "#" o "javascript:void(0)"?.

Author: Community, 2008-10-29

7 answers

Disfruto bastante El artículo de Matt Kruse sobre las Mejores Prácticas de Javascript. En él, afirma que usar la sección href para ejecutar código JavaScript es una mala idea. A pesar de que ha declarado que sus usuarios deben tener JavaScript habilitado, no hay razón por la que no pueda tener una página HTML simple a la que todos sus enlaces JavaScript puedan apuntar para su sección href en el caso de que alguien desactive JavaScript después de iniciar sesión. Le animaría a que todavía permita esta alternativa mecanismo. Algo como esto se adherirá a las "mejores prácticas" y logrará su objetivo:

<a href="javascript_required.html" onclick="doSomething(); return false;">go</a>
 63
Author: cowgod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-02 14:02:17

¿Por qué hacer esto cuando se puede utilizar addEventListener/attachEvent? Si no hay un href-equivalente, no utilice un <a>, utilice un <button> y estilo en consecuencia.

 10
Author: eyelidlessness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-01 05:32:45

Olvidaste otro método:

5: <a href="#" id="myLink">Link</a>

Con el código JavaScript:

document.getElementById('myLink').onclick = function() {
    // Do stuff.
};

No puedo comentar cuál de las opciones tiene el mejor soporte o cuál es semánticamente la mejor, pero solo diré que prefiero este estilo porque separa su contenido de su código JavaScript. Mantiene todo el código JavaScript unido, que es mucho más fácil de mantener (especialmente si está aplicando esto a muchos enlaces), e incluso puede ponerlo en un archivo externo que luego se puede empaquetar para reducir el tamaño de los archivos y el almacenamiento en caché de los navegadores cliente.

 4
Author: nickf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-02 14:06:07
<a href="#" onClick="DoSomething(); return false;">link</a>

Haré esto, o:

<a href="#" id = "Link">link</a>
(document.getElementById("Link")).onclick = function() {
    DoSomething();
    return false;
};

Dependiendo de la situación. Para aplicaciones más grandes, la segunda es la mejor porque consolida el código de tu evento.

 3
Author: nlaq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 04:12:24

El método #2 tiene un error de sintaxis en FF3 e IE7. Prefiero los métodos #1 y #3, porque #4 ensucia el URI con '#' aunque causa menos tipeo... Obviamente, como se señaló en otras respuestas, la mejor solución es separar el html del manejo de eventos.

 1
Author: Pier Luigi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-29 07:19:58

Solo navegadores modernos

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }
    doc.addEventListener('click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault();
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Navegador cruzado

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var cb_addEventListener = function(obj, evt, fnc) {
        // W3C model
        if (obj.addEventListener) {
            obj.addEventListener(evt, fnc, false);
            return true;
        } 
        // Microsoft model
        else if (obj.attachEvent) {
            return obj.attachEvent('on' + evt, fnc);
        }
        // Browser don't support W3C or MSFT model, go on with traditional
        else {
            evt = 'on'+evt;
            if(typeof obj[evt] === 'function'){
                // Object already has a function on traditional
                // Let's wrap it with our own function inside another function
                fnc = (function(f1,f2){
                    return function(){
                        f1.apply(this,arguments);
                        f2.apply(this,arguments);
                    }
                })(obj[evt], fnc);
            }
            obj[evt] = fnc;
            return true;
        }
        return false;
    };
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }

    cb_addEventListener(doc, 'click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault ? e.preventDefault() : e.returnValue = false;
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Puede ejecutar esto antes de que el documento esté listo, haciendo clic en los botones funcionará porque adjuntamos el evento al documento.

Fuentes:

 1
Author: Timo Huovinen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:47

Una diferencia que he notado entre esto:

<a class="actor" href="javascript:act1()">Click me</a>

Y esto:

<a class="actor" onclick="act1();">Click me</a>

Es que si en cualquier caso usted tiene:

<script>$('.actor').click(act2);</script>

Entonces para el primer ejemplo, act2 se ejecutará antes de act1 y en el segundo ejemplo, será al revés.

 0
Author: JoelFan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-01 17:48:48