Pourquoi les frameworks / bibliothèques JavaScript ont-ils des fonctions qui existent déjà en JavaScript pur?

61

Je me demande pourquoi les frameworks / bibliothèques ont leurs propres assistants alors qu'ils existent déjà en natif.

Prenons jQuery et AngularJS . Ils ont leurs propres eachfonctions d'itérateur:

Mais nous avons Array.prototype.forEach.

De même,

Mais nous avons la JSON.parse()fonction en JavaScript vanille.

Cihad Turhan
la source
75
En tant que personne qui se souvient du mauvais temps du développement Web, cette question me fait pleurer.
josh3736
3
@ josh3736 Au moins, vous n'avez pas encore besoin de supporter IE6 (mais, heureusement, de manière "fais-le marcher, ça peut ressembler à de la merde")
Izkata Le
12
jQuery.eachet Array.prototype.forEachne sont pas équivalents.
zzzzBov
3
Ce que vous devriez vous demander est la suivante: dans quelle mesure les fonctions présentes dans vanillaJS proviennent-elles de boîtes à outils telles que jQ et autres? La réponse est: beaucoup . Cela soulève la question: pourquoi les utilisons-nous toujours? Pourquoi inclure jQuery $.each, et ne pas utiliser le natif (et plus rapidement) Array.prototype.forEach?
Elias Van Ootegem
1
@ josh3736 C'est bon, mon frère ... i.stack.imgur.com/HJs4V.jpg
Crono

Réponses:

94

Parce que, lorsque ces bibliothèques ont été écrites, certains des principaux navigateurs ne supportaient pas ces fonctionnalités. Une fois écrites et utilisées, ces fonctionnalités ne peuvent pas être supprimées de ces bibliothèques sans interrompre de nombreuses applications.

(Dans ce cas, "navigateur principal" signifie un navigateur qui détient toujours une part de marché importante, y compris d'anciennes versions de navigateurs tels qu'Internet Explorer, où un grand nombre d'utilisateurs ne passe pas nécessairement à la dernière version.)

Gort le robot
la source
44
$ ('marquee'). each (function () {$ (this) .append ($ ('<bgsound />' ', {src: "good-answer.mp3"}));});
Pierre Arlaud
37
@dirkk Ce n'est pas que les navigateurs récents ne le supportent pas. C’est que tout le monde n’a pas la chance d’avoir un public utilisant un navigateur récent.
George Reith
14
Array.prototype.forEachitère uniquement sur des tableaux - les deux fonctions d'itérateur de bibliothèque peuvent parcourir des tableaux ou des objets.
JoeG
3
Les fonctions sont là pour prendre en charge les anciens navigateurs et l'ancien code qui appelle la bibliothèque et que le programmeur ne veut pas réécrire. Même si vous avez abandonné le support pour IE 6, vous avez probablement encore du JavaScript en cours d'utilisation lorsque vous avez besoin de prendre en charge des copies anciennes d'IE.
Michael Shopsin
6
Beaucoup de ces fonctions (par exemple, jQuery.parseJSON ()) vérifient simplement si le navigateur le prend en charge, puis s’adapte à la méthode du navigateur et n’utilise une alternative que sur des navigateurs non compatibles!
Josef
35

Parce que différents navigateurs ont différentes implémentations et fonctionnalités intégrées dans leur moteur JavaScript. Le même code "vanilla-JS" peut s'exécuter différemment sur deux navigateurs différents, voire même sur deux versions différentes du même navigateur.

La couche d'abstraction fournie par les bibliothèques JS populaires est un moyen de contourner ce problème. En coulisse, il s’appuie sur les capacités et les limites des différents navigateurs et offre une API unifiée et facile à utiliser. Ceci, à son tour, permet aux opérations courantes telles que l’obtention d’un objet DOM ou l’extraction de données JSON d’être cohérentes, efficaces et indépendantes du navigateur.

Cela facilite beaucoup la vie des développeurs qui peuvent désormais se concentrer sur ce que le code doit faire, plutôt que sur la manière dont il devrait être écrit pour fonctionner avec le navigateur X ou Y.

Crono
la source
2
Le comportement de "core JS" est bien spécifié et testé sur tous les navigateurs.
Domenic
2
@Domenic Syntax de côté, les implémentations de javascript diffèrent d'un navigateur à l'autre. Il existe des propriétés, des méthodes, des événements et des fonctionnalités que vous ne trouverez que dans quelques navigateurs, voire même parfois dans un seul.
Crono
1
Oui, les navigateurs ont des fonctionnalités non standard. Cela n'a rien à voir avec les fonctionnalités standard présentées dans cette question.
Domenic
8
@Domenic Si par "caractéristiques standard discutées dans la question" vous voulez dire les fonctions Array.prototype.forEachet JSON.parse, une recherche rapide sur Google vous montrera que vous vous trompez. JSONL'objet n'était pas pris en charge sur IE7 et forEachn'était pas défini sur certaines versions d'Opera. Des bibliothèques telles que jQuery étaient toutefois au courant de ces limitations et les contournaient dans les coulisses. Je pense donc que ma réponse est valable.
Crono
28

1. Compatibilité descendante

JavaScript est une implémentation de ECMAScript . La plupart de ces fonctions ont été introduites dans ECMAScript 5 (ES5). Cependant, de nombreux navigateurs plus anciens, qui possèdent encore une part assez importante du marché, ne prennent pas en charge ces fonctions (voir tableau de compatibilité ECMAScript 5 ), le plus notable étant IE8.

Généralement, les bibliothèques reviendront à l'implémentation native si elle existe, sinon elles utiliseront leur propre polyfill, par exemple, implémentons 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;
}

Les lignes suivantes vérifient si la forEachméthode existe sur l’objet et s’il s’agit de la version AngularJS ou non. Sinon, il utilise la fonction déjà spécifiée (la version native):

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

2. Commodité

En JavaScript natif, Array.prototype.forEachcette méthode est exclusive à une instance de Array. Toutefois, la plupart des Objectmodifications sont également itérables.

Pour cette raison, de nombreux créateurs de bibliothèques rendent leurs fonctions polymorphes (pouvant accepter plusieurs types en entrée). Prenons le code AngularJS ci-dessus et voyons quelles entrées il accepte:

Fonctions :

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);
    }
  }

Tableaux (avec support natif pour chaque):

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

Objets de type tableau, y compris Array (sans support natif de forEach), String, HTMLElement, Object avec une propriété de longueur valide:

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

Objets:

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

Conclusion

Comme vous pouvez le constater, AngularJS itérera sur la plupart des objets JavaScript, bien que fonctionnant de la même manière que la fonction native, il accepte beaucoup plus de types d’entrées et constitue donc un ajout valable à la bibliothèque ainsi qu’un moyen d’apporter des fonctions ES5. aux anciens navigateurs.

George Reith
la source
2
Vous voudrez peut-être mettre à jour votre lien pour qu'il pointe vers un commit particulier (par exemple, angular.js L203-257 ) pour pouvoir vous y référer ultérieurement, une fois mastermodifié.
Whymarrh