¿Por qué los frameworks / bibliotecas de JavaScript tienen funciones que ya existen en JavaScript puro?

61

Me pregunto por qué los frameworks / bibliotecas tienen sus propios ayudantes, aunque ya existen de forma nativa.

Tomemos jQuery y AngularJS . Tienen sus propias eachfunciones de iterador:

Pero nosotros tenemos Array.prototype.forEach.

Similar,

Pero tenemos la JSON.parse()función en JavaScript vainilla.

Cihad Turhan
fuente
75
Como alguien que recuerda los viejos tiempos del desarrollo web, esta pregunta me hace llorar.
josh3736
3
@ josh3736 Al menos aún no tienes que soportar IE6 (aunque, afortunadamente, solo en una forma de "hacer que funcione, puede parecer una mierda")
Izkata
12
jQuery.eachy Array.prototype.forEachno son equivalentes
zzzzBov
3
Lo que debe preguntarse es: ¿cuántas de las funciones que se encuentran en vanillaJS ahora, se originaron en kits de herramientas como jQ y similares? La respuesta es: muchas . Esto plantea la pregunta: ¿por qué los seguimos usando? ¿Por qué incluir jQuery's $.eachy no usar el nativo (y más rápido) Array.prototype.forEach?
Elias Van Ootegem
1
@ josh3736 Está bien hermano ... i.stack.imgur.com/HJs4V.jpg
Crono

Respuestas:

94

Porque cuando se escribieron esas bibliotecas, algunos navegadores importantes no admitían esas características. Una vez escritas y utilizadas, estas características no se pueden eliminar de estas bibliotecas sin romper muchas aplicaciones.

(En este caso, "navegador principal" significa un navegador que todavía tiene una gran cuota de mercado, que incluye versiones anteriores de navegadores como Internet Explorer, donde un gran número de usuarios no necesariamente se actualiza a la última versión).

Gort the Robot
fuente
44
$ ('marquee'). each (function () {$ (this) .append ($ ('<bgsound />', {src: "good-answer.mp3"}));});
Pierre Arlaud
37
@dirkk No es que los navegadores recientes no lo admitan. Es que no todos tienen la suerte de tener una audiencia que usa un navegador reciente.
George Reith
14
Array.prototype.forEachitera solo sobre matrices: ambas funciones de iterador de biblioteca pueden iterar sobre matrices u objetos.
JoeG
3
Las funciones están ahí para admitir navegadores antiguos y para admitir código antiguo que llama a la biblioteca y el programador no quiere reescribir. Incluso si ha dejado de admitir IE 6, es probable que todavía tenga JavaScript en uso escrito cuando necesitaba admitir copias antiguas de IE.
Michael Shopsin
66
Muchas de estas funciones (por ejemplo, jQuery.parseJSON ()) solo comprueban si el navegador lo admite y luego se ajusta al método del navegador, ¡y solo usa una alternativa en navegadores no compatibles!
Josef
35

Debido a que diferentes navegadores tienen diferentes implementaciones y características integradas en su motor de JavaScript. El mismo código "vanilla-JS" podría ejecutarse de manera diferente en dos navegadores diferentes, o incluso en dos versiones diferentes del mismo navegador.

La capa de abstracción proporcionada por las bibliotecas JS populares es una forma de evitar esto. Detrás de escena, trabaja alrededor de las diferentes capacidades y limitaciones de los navegadores y ofrece una API unificada y fácil de usar. Esto, a su vez, permite que las operaciones comunes, como obtener un objeto DOM o obtener datos JSON, sean consistentes, eficientes y independientes del navegador.

Esto hace la vida mucho más fácil para los desarrolladores que ahora pueden centrarse en lo que debe hacer el código, en lugar de cómo debe escribirse para que funcione con el navegador X o Y.

Crono
fuente
2
El comportamiento de "core JS" está bien especificado y probado en todos los navegadores.
Domenic
2
Dejando de lado la sintaxis de @Domenic, las implementaciones de JavaScript difieren de un navegador a otro. Hay propiedades, métodos, eventos y características que encontrará en solo unos pocos navegadores, o incluso solo en uno a veces.
Crono
1
Sí, los navegadores tienen características no estándar. Eso no tiene nada que ver con las características estándar discutidas en esta pregunta.
Domenic
8
@Domenic Si por "características estándar discutidas en la pregunta" te refieres a las funciones Array.prototype.forEachy JSON.parse, una búsqueda rápida en Google te mostrará que estás equivocado. JSONEl objeto no era compatible con IE7 y forEachno estaba definido en algunas versiones de Opera. Sin embargo, las bibliotecas como jQuery conocían estas limitaciones y trabajaban en torno a ellas detrás de escena. Así que creo que mi respuesta se mantiene.
Crono
28

1. Compatibilidad con versiones anteriores

JavaScript es una implementación de ECMAScript . La mayoría de esas funciones se introdujeron en ECMAScript 5 (ES5), sin embargo, muchos navegadores antiguos que todavía tienen una participación lo suficientemente significativa en el mercado no son compatibles con estas funciones (consulte la tabla de compatibilidad de ECMAScript 5 ), la más notable de ellas es IE8.

En general, las bibliotecas volverán a la implementación nativa si existe; de ​​lo contrario, use su propio polyfill, por ejemplo, veamos la implementación de AngularJS ( angular.js L203-257 ):

function forEach(obj, iterator, context) {
  var key;
  if (obj) {
    if (isFunction(obj)){
      for (key in obj) {
        // Need to check if hasOwnProperty exists,
        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
          iterator.call(context, obj[key], key);
        }
      }
    } else if (obj.forEach && obj.forEach !== forEach) {
      obj.forEach(iterator, context);
    } else if (isArrayLike(obj)) {
      for (key = 0; key < obj.length; key++)
        iterator.call(context, obj[key], key);
    } else {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          iterator.call(context, obj[key], key);
        }
      }
    }
  }
  return obj;
}

Las siguientes líneas verifican si el forEachmétodo existe en el objeto y si es la versión AngularJS o no. Si no, utiliza la función ya especificada (la versión nativa):

} else if (obj.forEach && obj.forEach !== forEach) {
  obj.forEach(iterator, context);
}

2. Conveniencia

En JavaScript nativo Array.prototype.forEaches un método exclusivo de una instancia de Array, sin embargo, la mayoría de cualquiera Objectes iterable también.

Por esta razón, muchos creadores de bibliotecas hacen que sus funciones sean polimórficas (capaces de aceptar múltiples tipos como entrada). Tomemos el código AngularJS anterior y veamos qué entradas acepta:

Funciones :

if (isFunction(obj)){
  for (key in obj) {
    // Need to check if hasOwnProperty exists,
    // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
    if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
      iterator.call(context, obj[key], key);
    }
  }

Matrices (con soporte nativo para cada uno):

} else if (obj.forEach && obj.forEach !== forEach) {
  obj.forEach(iterator, context);

Objetos de tipo Array, incluidos Array (sin soporte nativo para cada uno), String, HTMLElement, Object con una propiedad de longitud válida:

} else if (isArrayLike(obj)) {
  for (key = 0; key < obj.length; key++)
    iterator.call(context, obj[key], key);

Objetos:

} else {
  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      iterator.call(context, obj[key], key);
    }
  }
}

Conclusión

Como puede ver, AngularJS iterará sobre la mayoría de los objetos JavaScript, aunque funciona de la misma manera que la función nativa, acepta muchos más tipos diferentes de entrada y, por lo tanto, es una adición válida a la biblioteca y una forma de traer funciones ES5 a navegadores heredados.

George Reith
fuente
2
Es posible que desee actualizar su enlace para que apunte a una confirmación particular (por ejemplo, angular.js L203-257 ) para referencia futura una vez que mastercambie.
Whymarrh