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

87

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

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, debo asumir que JavaScript está habilitado (no pueden iniciar sesión sin él).

Personalmente, me gusta la opción 2 ya que le permite ver qué se va a ejecutar, especialmente útil cuando se depura dónde se pasan parámetros 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 a seguir, pero en realidad, # no es "real". Irá absolutamente a ninguna parte.

¿Hay alguno que no sea compatible o sea realmente malo, cuando sabe que el usuario tiene habilitado JavaScript?

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

Darryl Hein
fuente
Pequeño problema de sintaxis: la opción n. ° 2 debería ser: <a href="javascript:DoSomething();"> enlace </a> sin el "retorno"
DRosenfeld
Cambie la respuesta aceptada a la respuesta de @eyelidlessness. Creo que es el mejor enfoque, porque se preocupa por la semántica.
Michał Perłakowski

Respuestas:

69

Disfruto bastante del artículo de Matt Kruse sobre las mejores prácticas de JavaScript . En él, afirma que usar la hrefsección para ejecutar código JavaScript es una mala idea. A pesar de que ha indicado que sus usuarios deben tener JavaScript habilitado, no hay ninguna razón por la que no pueda tener una página HTML simple a la que todos sus enlaces de JavaScript puedan apuntar para su hrefsección en caso de que alguien apague JavaScript después de iniciar sesión. Le recomiendo encarecidamente que siga permitiendo este mecanismo de reserva. 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>
dios de la vaca
fuente
4
como el valor href se mostrará al usuario en la barra de estado? (la barra en la parte inferior) Consideraría usar un enlace un poco más fácil de usar, por ejemplo. "js.html? doSomething" la página aún puede ser HTML estático. De esta forma, el usuario verá claramente una diferencia entre los enlaces.
Gene
7
Puede anular este valor con el atributo de título, por ejemplo, <a href="javascript_required.html" title="Does Something" onclick="doSomething(); return false;"> go </a>
Conspicuous Compiler
Debería ser una buena práctica registrar las solicitudes en la página javascript_required.html y registrar la función que causó el error.
Timo Huovinen
2
¿Has pensado en las consecuencias para el SEO?
DanielBlazquez
Javascripttoolbox.com de Matt Kruse parece estar fuera de línea y a la venta.
showdev
10

¿Por qué harías esto cuando puedes usar addEventListener/ attachEvent? Si no hay href-equivalente, no use un <a>, use un <button>y ajústelo en consecuencia.

falta de párpados
fuente
9
utilizar un botón en lugar de un enlace no es una opción viable en muchos casos.
nickf
2
Porque se ve feo. Puede agregar un icono al lado del enlace. Son difíciles de formatear de la misma manera en todos los navegadores. Y, en general, las personas se mueven hacia enlaces en lugar de botones; observe la mayor parte de la pila sobre el flujo.
Darryl Hein
2
¿Se ve feo? Se parece a lo que quieras que se vea. De hecho, creo que los botones en realidad tienen más flexibilidad de estilo que los enlaces, ya que están en línea pero pueden llevar el relleno correctamente en los navegadores. Todo lo que se puede hacer con un enlace se puede hacer con un botón, con respecto a CSS.
párpados
2
Span no puede centrarse en el teclado.
Bobince
3
Y el botón es (jadeo) semánticamente correcto. Span es semánticamente sin sentido. Un botón es exactamente lo que el autor pretende utilizar, semánticamente.
párpados
5

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 la mejor semánticamente, pero solo diré que prefiero este estilo porque separa tu contenido de tu código JavaScript. Mantiene todo el código JavaScript junto, 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 y almacenar en caché por los navegadores del cliente.

nickf
fuente
7
Si tiene 20 o 30 enlaces diferentes con JS, esto puede volverse bastante tedioso y terminar con mucho JS.
Darryl Hein
no es más tedioso que recorrer HTML para cambiar javascript. ... o podría usar algo como jQuery que puede cambiar fácilmente los eventos en múltiples elementos a la vez ... $ ('# menú a'). click (function () {..})
nickf
1
@JKirchartz No veo cómo es predicar si hay razones detrás de la respuesta. Si lees la pregunta, realmente es un "cuál de estos 4 es el mejor", y acabo de señalar que hay otra opción que no había considerado.
nickf
No importa, trololo, al elegir entre ABC y D, uno no elige E.
JKirchartz
3
@JKirchartz Sí, no creo que entiendas realmente el propósito de Stack Overflow. Si alguien pregunta "¿Qué es mejor para crear una aplicación web en: Cobol o Fortran?" Es aceptable decirle a esa persona que no ha considerado todas las posibilidades. Claramente, la pregunta no es "cuál de estas cuatro cosas es la mejor".
nickf
3
<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 luego consolida su código de evento.

Anik Islam Abhi
fuente
Si tiene 20 o 30 enlaces diferentes con JS, esto puede volverse bastante tedioso y terminar con mucho JS.
Darryl Hein
y los errores que se introducen en su código pueden ser MUY difíciles de depurar. Estos errores aparecen muy fácilmente, como lo demuestra su primer ejemplo. :)
nickf
1

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

Pier Luigi
fuente
Método # 2 de qué? Las preguntas no permanecen en el mismo orden que cuando las vio.
Diodeus - James MacFarlane
El método # 4 no estropeará el URI si te aseguras de hacerlo return false. Por esa razón, el método # 4 es probablemente el mejor (de los enumerados).
Már Örlygsson
2
@Diodeus, creo que Pier se refería a la lista numerada dentro de la pregunta , que de hecho ha estado allí desde que se publicó la pregunta en primer lugar.
párpados
1

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 tienes:

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

luego, para el primer ejemplo, act2se ejecutará antes act1y en el segundo ejemplo, será al revés.

JoelFan
fuente
1

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, hacer clic en los botones funcionará porque adjuntamos el evento al documento.

Fuentes:

Timo Huovinen
fuente