¿Cuándo usar Vanilla JavaScript vs.JQuery?

238

Al monitorear / intentar responder preguntas comunes de jQuery, he notado que hay ciertas prácticas que usan JavaScript, en lugar de jQuery, que realmente le permiten escribir menos y hacer ... bueno, la misma cantidad. Y también puede producir beneficios de rendimiento.

Un ejemplo especifico

$(this) vs this

Dentro de un evento de clic que hace referencia a la identificación de los objetos en los que se hizo clic

jQuery

$(this).attr("id");

Javascript

this.id;

¿Hay alguna otra práctica común como esta? Donde ciertas operaciones de Javascript podrían realizarse más fácilmente, sin incluir jQuery en la mezcla. ¿O es este un caso raro? (de un "acceso directo" jQuery que realmente requiere más código)

EDITAR: Si bien aprecio las respuestas con respecto al rendimiento de jQuery frente a JavaScript simple, en realidad estoy buscando respuestas mucho más cuantitativas. Al usar jQuery , casos en los que uno estaría mejor (legibilidad / compacidad) para usar JavaScript simple en lugar de usar $(). Además del ejemplo que di en mi pregunta original.

jondavidjohn
fuente
No estoy seguro de entender la pregunta. ¿Estaba buscando opiniones sobre los méritos del uso del código de la biblioteca, o estaba buscando técnicas adicionales compatibles con otros navegadores que no sean jQuery this.id?
user113716
1
Según las respuestas, parece que todo el mundo está tomando esta pregunta como filosófica, ya que pretendía que fuera muy cuantitativa, ya que casi compila una lista de casos como el que describí que son prácticas comunes (mal).
jondavidjohn

Respuestas:

207
  • this.id (como sabes)
  • this.value(en la mayoría de los tipos de entrada. Solo los problemas que conozco son IE cuando a <select>no tiene valuepropiedades establecidas en sus <option>elementos o entradas de radio en Safari).
  • this.className para obtener o establecer una propiedad de "clase" completa
  • this.selectedIndexcontra a <select>para obtener el índice seleccionado
  • this.optionscontra un <select>para obtener una lista de <option>elementos
  • this.textcontra un <option>para obtener su contenido de texto
  • this.rowscontra un <table>para obtener una colección de <tr>elementos
  • this.cellscontra a <tr>para obtener sus células (td y th)
  • this.parentNode conseguir un padre directo
  • this.checkedpara comprobar el estado de un checkbox Gracias @Tim Down
  • this.selectedpara obtener el estado seleccionado de un option Thanks @Tim Down
  • this.disabledpara obtener el estado desactivado de un input Thanks @Tim Down
  • this.readOnlypara obtener el estado de solo lectura de un input gracias @Tim Down
  • this.hrefcontra un <a>elemento para obtener suhref
  • this.hostnamecontra un <a>elemento para obtener el dominio de suhref
  • this.pathnamecontra un <a>elemento para obtener el camino de suhref
  • this.searchcontra un <a>elemento para obtener la cadena de consulta de suhref
  • this.src contra un elemento donde es válido tener un src

... Creo que tienes la idea.

Habrá momentos en que el rendimiento es crucial. Al igual que si realiza algo en un ciclo muchas veces, es posible que desee deshacerse de jQuery.

En general, puede reemplazar:

$(el).attr('someName');

con:

Arriba estaba mal redactado. getAttributeno es un reemplazo, pero recupera el valor de un atributo enviado desde el servidor, y su correspondiente setAttributelo establecerá. Necesario en algunos casos.

Las siguientes oraciones lo cubrieron. Vea esta respuesta para un mejor tratamiento.

el.getAttribute('someName');

... para acceder a un atributo directamente. Tenga en cuenta que los atributos no son lo mismo que las propiedades (aunque a veces se reflejan entre sí). Por supuesto que setAttributetambién hay.

Supongamos que tuvo una situación en la que recibió una página en la que necesita desenvolver todas las etiquetas de un determinado tipo. Es corto y fácil con jQuery:

$('span').unwrap();  // unwrap all span elements

Pero si hay muchos, es posible que desee hacer una pequeña API DOM nativa:

var spans = document.getElementsByTagName('span');

while( spans[0] ) {
    var parent = spans[0].parentNode;
    while( spans[0].firstChild ) {
        parent.insertBefore( spans[0].firstChild, spans[0]);
    }
    parent.removeChild( spans[0] );
}

Este código es bastante corto, funciona mejor que la versión jQuery y puede convertirse fácilmente en una función reutilizable en su biblioteca personal.

Puede parecer que tengo un bucle infinito con el exterior whiledebido a while(spans[0]), pero debido a que estamos tratando con una "lista en vivo", se actualiza cuando hacemos el parent.removeChild(span[0]);. Esta es una característica bastante ingeniosa que nos perdemos cuando trabajamos con una matriz (u objeto similar a una matriz).

usuario113716
fuente
2
agradable ... por lo que en su mayoría gira en torno a esta palabra clave que se envuelve innecesariamente en un objeto jQuery.
jondavidjohn
1
@jondavidjohn: Bueno, hay algunas correcciones que son buenas en algunos casos, como this.valuedonde hay un par de peculiaridades del navegador en ciertos casos. Todo depende de tu necesidad. Hay muchas técnicas agradables que son fáciles sin jQuery, especialmente cuando el rendimiento es crucial. Trataré de pensar en más.
user113716
3
Estaba a punto de escribir una respuesta, pero en su lugar agregaré sugerencias para la suya. En general, attr()se usa en exceso de forma masiva. Si solo se trata de un elemento, rara vez lo necesitará attr(). Dos de mis favoritos son la confusión en torno a la checkedpropiedad de las casillas de verificación (todo tipo de esferas místicas en torno a que una: $(this).attr("checked", "checked"), $(this).is(":checked")etc.) y del mismo modo la selectedpropiedad de los <option>elementos.
Tim Down
1
Aaargh, @patrick, noooo: lo has recomendado getAttribute(). Casi nunca lo necesita : está roto en IE, no siempre refleja el estado actual y no es lo que jQuery hace de todos modos. Solo usa propiedades. stackoverflow.com/questions/4456231/…
Tim Down
1
Estuve usando JS durante tanto tiempo y no sabía sobre className, thx.
IAdapter
60

La respuesta correcta es que siempre tendrá una penalización de rendimiento cuando use jQuery en lugar de JavaScript nativo 'simple'. Eso es porque jQuery es una biblioteca de JavaScript. No es una nueva versión elegante de JavaScript.

La razón por la que jQuery es poderoso es porque hace algunas cosas que son demasiado tediosas en una situación de navegador cruzado (AJAX es uno de los mejores ejemplos) y suaviza las inconsistencias entre la miríada de navegadores disponibles y proporciona una API consistente. También facilita fácilmente conceptos como encadenamiento, iteración implícita, etc., para simplificar el trabajo en grupos de elementos juntos.

Aprender jQuery no sustituye el aprendizaje de JavaScript. Debes tener una base firme en este último para que aprecies completamente lo que saber lo primero te está haciendo más fácil.

- Editado para abarcar comentarios -

Como los comentarios son rápidos de señalar (y estoy de acuerdo con el 100%), las declaraciones anteriores se refieren al código de evaluación comparativa. Una solución JavaScript 'nativa' (suponiendo que esté bien escrita) superará a una solución jQuery que logra lo mismo en casi todos los casos (de lo contrario me encantaría ver un ejemplo). jQuery acelera el tiempo de desarrollo, lo cual es un beneficio significativo que no quiero minimizar. Facilita un código fácil de leer y fácil de seguir, que es más de lo que algunos desarrolladores son capaces de crear por sí mismos.

En mi opinión, entonces, la respuesta depende de lo que intentes lograr. Si, como supuse en función de su referencia a los beneficios de rendimiento, está buscando la mejor velocidad posible de su aplicación, entonces el uso de jQuery introduce gastos generales cada vez que llama $(). Si buscas legibilidad, consistencia, compatibilidad cruzada entre navegadores, etc., entonces ciertamente hay razones para favorecer jQuery sobre JavaScript 'nativo'.

gddc
fuente
8
Me encantaría ver un ejemplo de una situación en la que jQuery puede superar una implementación en JS puro. No importa lo que haga, si está utilizando jQuery (o cualquier otra biblioteca) tiene una sobrecarga funcional que es inevitable. No hay forma de alejarse de los (aunque) gastos generales menores generados por las llamadas $(). Si no haces esa llamada, ahorras tiempo.
gddc
16
Una solución casera mal escrita probablemente sería más lenta. El equipo de jQuery ha ejecutado algunos JavaScript altamente eficientes en el paquete. Ver la respuesta de @ Freelancer.
Stephen
3
Una solución mal escrita siempre será una solución mal escrita, y eso no es culpa del idioma. No cambia el hecho de que la biblioteca incurrirá en gastos generales que una función 'nativa' podría evitar si se piensa bien.
gddc
11
@gddc Creo que el mejor ejemplo donde jQuery "supera" (leído fuera del cuadro de referencia) JS puro es reducir el tiempo de desarrollo (que es un valor masivo para el negocio) y simplificar la experimentación
Ben
13
Todo lo que ha escrito es cierto, pero ha omitido lo que @Ben señala arriba. jQuery hace que el desarrollador sea más rápido y más robusto. Vea esta implementación de KillClass () que escribí hace muchos años y que utilicé mucho. ¿Sabes que? Está roto para ciertos casos extremos. El código deficiente es un código deficiente y el código incorrecto es un código incorrecto, pero el uso de jQuery a menudo hace que el desarrollador escriba un código mejor y más correcto. La mayoría de las veces, las computadoras son lo suficientemente rápidas; son los desarrolladores quienes necesitan la ayuda.
Phrogz
38

Hay un marco llamado ... ¿adivina qué? Vanilla JS. Espero que entiendas el chiste ...: D sacrifica la legibilidad del código por el rendimiento ... Al compararlo a jQuerycontinuación, puedes ver que recuperar un DOMelemento IDes casi 35 veces más rápido. :)

Entonces, si desea rendimiento, es mejor que pruebe Vanilla JS y saque sus propias conclusiones. Tal vez no experimente JavaScript colgando la GUI del navegador / bloqueando el hilo de la interfaz de usuario durante el código intensivo como dentro de un forbucle.

Vanilla JS es un marco rápido, ligero y multiplataforma para crear aplicaciones JavaScript increíbles y potentes.

En su página de inicio hay algunas comparaciones de rendimiento:

ingrese la descripción de la imagen aquí

revs Leniel Macaferi
fuente
1
@Leniel Macaferi ¡Oh, hombre, me encantó esta respuesta! ¡No me di cuenta de que el rendimiento entre vainilla y otros marcos podría marcar una gran diferencia! De todos modos Salón de la fama por esta respuesta !! PD: ¿También hiciste el sitio web?
Steve
17

Ya hay una respuesta aceptada, pero creo que ninguna respuesta escrita directamente aquí puede ser exhaustiva en su lista de métodos / atributos nativos de JavaScript que prácticamente ha garantizado la compatibilidad entre navegadores. Para eso puedo redirigirte a quirksmode:

http://www.quirksmode.org/compatibility.html

Es quizás la lista más completa de lo que funciona y lo que no funciona en qué navegador en cualquier lugar. Presta especial atención a la sección DOM. Es mucho para leer, pero el punto no es leerlo todo sino usarlo como referencia.

Cuando comencé a escribir aplicaciones web en serio, imprimí todas las tablas DOM y las colgué en la pared para saber de un vistazo qué es seguro usar y qué requiere pirateo. En estos días solo busco en Google algo como quirksmode parentNode compatibilitycuando tengo dudas.

Como cualquier otra cosa, el juicio es principalmente una cuestión de experiencia. Realmente no le recomendaría que lea todo el sitio y memorice todos los problemas para averiguar cuándo usar jQuery y cuándo usar JS simple. Solo ten en cuenta la lista. Es bastante fácil de buscar. Con el tiempo desarrollará un instinto de cuándo es preferible JS simple.


PD: PPK (el autor del sitio) también tiene un libro muy bueno que recomiendo leer.

slebetman
fuente
14

Cuando:

  1. usted sabe que existe una compatibilidad inquebrantable entre navegadores para lo que está haciendo, y
  2. no es significativamente más código para escribir, y
  3. no es significativamente menos legible, y
  4. Usted está razonablemente seguro de que jQuery no elegirá diferentes implementaciones basadas en el navegador para lograr un mejor rendimiento, entonces:

usa JavaScript. De lo contrario, use jQuery (si puede).

Editar : Esta respuesta se aplica tanto al elegir usar jQuery en general como al dejarlo fuera, así como al elegir si se va a usar vanilla JS dentro de jQuery. Elegir entre attr('id')y se .idinclina a favor de JS, mientras se elige entre removeClass('foo')y se .className = .className.replace( new Regexp("(?:^|\\s+)"+foo+"(?:\\s+|$)",'g'), '' )inclina a favor de jQuery.

Phrogz
fuente
3
Creo que el OP tiene la intención de usar jQuery, pero se pregunta dónde y cuándo usar JavaScript nativo dentro de sus métodos jQuery.
Stephen
.classList.remove('foo')parece funcionar bien en los navegadores más nuevos
Tyilo
3
@Tyilo classList.remove es parte de HTML5 ClassList API que no se implementa en IE9 por ejemplo caniuse.com/#feat=classlist
Corbacho
13

Las respuestas de otros se han centrado en la amplia pregunta de "jQuery vs. JS simple". A juzgar por su OP, creo que simplemente se preguntaba cuándo es mejor usar vanilla JS si ya eligió usar jQuery. Su ejemplo es un ejemplo perfecto de cuándo debe usar vanilla JS:

$(this).attr('id');

Es más lento y (en mi opinión) menos legible que:

this.id.

Es más lento porque debe girar un nuevo objeto JS solo para recuperar el atributo de la manera jQuery. Ahora, si vas a usar $(this)para realizar otras operaciones, entonces, por supuesto, almacena ese objeto jQuery en una variable y opera con eso. Sin embargo, me he encontrado con muchas situaciones en las que solo necesito un atributo del elemento (como ido src).

¿Hay alguna otra práctica común como esta? Donde ciertas operaciones de Javascript podrían realizarse más fácilmente, sin incluir jQuery en la mezcla. ¿O es este un caso raro? (de un "acceso directo" jQuery que realmente requiere más código)

Creo que el caso más común es el que describe en su publicación; personas envueltas $(this)en un objeto jQuery innecesariamente. Veo esto con mayor frecuencia con idy value(en lugar de usar $(this).val()).

Editar: Aquí hay un artículo que explica por qué usar jQuery en el attr()caso es más lento. Confesión: lo robé de la etiqueta wiki, pero creo que vale la pena mencionarlo para la pregunta.

Edite nuevamente: Dadas las implicaciones de legibilidad / rendimiento de solo acceder a los atributos directamente, diría que una buena regla general es intentar usarlo this.<attributename>cuando sea posible. Probablemente hay algunos casos en los que esto no funcionará debido a inconsistencias del navegador, pero probablemente sea mejor intentarlo primero y recurrir a jQuery si no funciona.

Andrew Whitaker
fuente
ja, gracias por leer la pregunta;) ... así que, en términos generales, ¿es la excepción?
jondavidjohn
@jondavidjohn: Sinceramente, dudo en hacer esa llamada. Creo que sí, por lo general, es una ventaja para usted usar jQuery debido a preocupaciones entre navegadores. Hay otros ejemplos, como this.style.display = 'none'. ¿Eso es mejor que $(this).hide()? Yo diría que el último es más legible, pero el primero es más rápido. No hace daño experimentar un poco usted mismo para ver si ciertas acciones funcionarán en los navegadores sin jQuery: esto es lo que hago normalmente antes de envolver un elemento en un objeto jQuery para realizar una operación.
Andrew Whitaker
10

Si está más preocupado por el rendimiento, su ejemplo principal da en el clavo. Invocar jQuery de forma innecesaria o redundante es, en mi humilde opinión, la segunda causa principal de un rendimiento lento (el primero es un mal recorrido del DOM).

No es realmente un ejemplo de lo que está buscando, pero veo esto con tanta frecuencia que merece la pena mencionar: una de las mejores formas de acelerar el rendimiento de sus scripts jQuery es almacenar en caché los objetos jQuery y / o usar el encadenamiento:

// poor
$(this).animate({'opacity':'0'}, function() { $(this).remove(); });

// excellent
var element = $(this);
element.animate({'opacity':'0'}, function() { element.remove(); });

// poor
$('.something').load('url');
$('.something').show();

// excellent
var something = $('#container').children('p.something');
something.load('url').show();
Stephen
fuente
interesante ... ¿esta separación de la creación de instancias var y la acción realmente conduce a ganancias de rendimiento de procesamiento? o simplemente permite que la acción se ejecute por sí sola (
suponiendo
1
Ciertamente conduce a ganancias de rendimiento, pero solo si reutiliza el elemento seleccionado. Entonces, en el último caso var something, realmente no necesitaba almacenar en caché el objeto jQuery (ya que solía encadenar), pero lo hago de todos modos por costumbre.
Stephen
2
Por otro lado, tome ese mismo ejemplo. Llamar $('.something')dos veces significa que jQuery debe atravesar el DOM dos veces buscando todos los elementos con ese selector.
Stephen
2
En el caso del primer ejemplo, el almacenamiento en caché $(this)reduce las llamadas a la función jQuery. Esto le dará la mayor ganancia en un escenario de bucle.
Stephen
2
@Alnitak Observe que elementes igual a $(this). Eso no contiene múltiples elementos.
Stephen
8

Descubrí que hay una superposición entre JS y JQ. El código que has mostrado es un buen ejemplo de eso. Francamente, la mejor razón para usar JQ sobre JS es simplemente la compatibilidad del navegador. Siempre me inclino hacia JQ, incluso si puedo lograr algo en JS.

Dutchie432
fuente
8
Sería una maravilla si no hubiera ninguna superposición, porque JQuery es JavaScript.
Simon
6

Esta es mi opinión personal, pero como jQuery es JavaScript de todos modos, creo que teóricamente no puede funcionar mejor que Vanilla JS.

Pero prácticamente puede funcionar mejor que JS escrito a mano, ya que el código escrito a mano puede no ser tan eficiente como jQuery.

En pocas palabras: para cosas más pequeñas, tiendo a usar Vanilla JS, para proyectos intensivos de JS me gusta usar jQuery y no reinventar la rueda, también es más productivo.

CodeVirtuoso
fuente
1
Hay muchos ejemplos en los que las bibliotecas superan a Vanilla JS. Resulta que muchos de los métodos prototipo incorporados de JS están mal escritos.
Estadísticas de aprendizaje con el ejemplo
3

La lista de propiedades en vivo de la primera respuesta thiscomo elemento DOM es bastante completa.

También te puede interesar conocer a otros.

Cuando este es el documento:

  • this.formspara obtener uno HTMLCollectionde los formularios de documentos actuales,
  • this.anchorspara obtener una HTMLCollectionde todas las cosas HTMLAnchorElementscon nameser establecido,
  • this.linkspara obtener una HTMLCollectionde todas las HTMLAnchorElements con la hrefconfiguración,
  • this.imagespara obtener una HTMLCollectionde todas las HTMLImageElements
  • y lo mismo con los applets en desuso como this.applets

Cuando trabaja con document.forms, document.forms[formNameOrId]obtiene el formulario llamado o identificado.

Cuando este es un formulario:

  • this[inputNameOrId] para obtener el campo llamado o identificado

Cuando este es el campo de formulario:

  • this.type para obtener el tipo de campo

Al aprender los selectores jQuery, a menudo omitimos el aprendizaje de las propiedades de elementos HTML ya existentes, a las que se accede tan rápido.

lib3d
fuente
Las propiedades que mencionó están definidas en la especificación HTML de Nivel 2 DOM y son ampliamente compatibles. document.embedsy document.pluginstambién son ampliamente compatibles (DOM 0). document.scriptstambién es una colección conveniente, definida en la especificación HTML5 y ampliamente compatible (y Firefox 9+ ).
Rob W
@Robw Entonces, la lista podría estar completa, y definitivamente útil y rápida. Gracias;)
lib3d
2

Como siempre, llego tarde a esta fiesta.

No fue la funcionalidad extra lo que me hizo decidir usar jQuery, por muy atractivo que fuera. Después de todo, nada le impide escribir sus propias funciones.

Fue el hecho de que había tantos trucos que aprender al modificar el DOM para evitar pérdidas de memoria (estoy hablando de ti, IE). Tener un recurso central que gestionara todo ese tipo de problemas para mí, escrito por personas que eran mucho mejores codificadores de JS que yo, que se revisaba, revisaba y probaba continuamente fue enviado por Dios.

Supongo que este tipo de cae bajo el argumento de soporte / abstracción de navegador cruzado.

Y, por supuesto, jQuery no impide el uso de JS directo cuando lo necesita. Siempre sentí que los dos parecían funcionar perfectamente juntos.

Por supuesto, si su navegador no es compatible con jQuery o si admite un entorno de gama baja (¿teléfono antiguo?), Un archivo .js grande podría ser un problema. ¿Recuerdas cuando jQuery solía ser pequeño?

Pero normalmente la diferencia de rendimiento no es motivo de preocupación. Solo tiene que ser lo suficientemente rápido. Con Gigahertz de ciclos de CPU que se desperdician cada segundo, estoy más preocupado por el rendimiento de mis codificadores, los únicos recursos de desarrollo que no duplican la potencia cada 18 meses.

Dicho esto, actualmente estoy investigando problemas de accesibilidad y, aparentemente, .innerHTML es un poco un no no con eso. jQuery, por supuesto, depende de .innerHTML, así que ahora estoy buscando un marco que dependa de los métodos algo tediosos que están permitidos. Y me imagino que dicho marco funcionará más lento que jQuery, pero siempre que funcione lo suficientemente bien, estaré feliz.

Swanny
fuente
2

Aquí hay una respuesta no técnica: muchos trabajos pueden no permitir ciertas bibliotecas, como jQuery.

De hecho, de hecho, Google no permite jQuery en ninguno de sus códigos (ni React, porque es propiedad de Facebook), que quizás no haya sabido hasta que el entrevistador diga "Lo siento, pero no puede usar jQuery, no está en la lista aprobada en XYZ Corporation ". Vanilla JavaScript funciona absolutamente en todas partes, siempre, y nunca te dará este problema. Si confías en una biblioteca, sí, obtienes velocidad y facilidad, pero pierdes la universalidad.

Además, hablando de entrevistas, la otra desventaja es que si dice que necesita usar una biblioteca para resolver un problema de JavaScript durante una prueba de código, parece que realmente no comprende el problema, lo que se ve un poco mal. Mientras que si lo resuelve en JavaScript sin formato, esto demuestra que realmente comprende y puede resolver cada parte de cualquier problema que se le presente.

Jack Connor
fuente
1

$(this)es diferente a this:

Al usarlo $(this), se asegura de que el prototipo jQuery se pase al objeto.

John Green
fuente