Perché i framework / librerie JavaScript hanno funzioni che già esistono in JavaScript puro?


61

Mi chiedo perché i framework / librerie abbiano i loro aiutanti sebbene esistano già in modo nativo.

Prendiamo jQuery e AngularJS . Hanno le loro eachfunzioni iteratore:

Ma abbiamo Array.prototype.forEach.

Allo stesso modo,

Ma abbiamo la JSON.parse()funzione in JavaScript vaniglia.


75
Come qualcuno che ricorda i brutti vecchi tempi dello sviluppo web, questa domanda mi fa piangere.
josh3736,

3
@ josh3736 Almeno non devi ancora supportare IE6 ('tho, fortunatamente solo in un modo "
fallo

12
jQuery.eache Array.prototype.forEachnon sono equivalenti.
zzzzBov

3
Quello che dovresti chiederti è: quante delle funzioni presenti in vanillaJS ora, provengono da toolkit come jQ e simili? La risposta è: molti . Questo fa sorgere la domanda: perché li stiamo ancora usando? Perché includere jQuery $.eache non usare il nativo (e più veloce) Array.prototype.forEach?
Elias Van Ootegem,

1
@ josh3736 Va bene amico ... i.stack.imgur.com/HJs4V.jpg
Crono

Risposte:


94

Perché quando quelle librerie sono state scritte, alcuni dei principali browser non supportavano quelle funzionalità. Una volta scritte e utilizzate, queste funzionalità non possono essere rimosse da queste librerie senza interrompere molte applicazioni.

(In questo caso, "browser principale" indica un browser che ha ancora una grande quota di mercato, che include versioni precedenti di browser come Internet Explorer, in cui un gran numero di utenti non si aggiorna necessariamente all'ultima versione.)


44
$ ('marquee'). each (function () {$ (this) .append ($ ('<bgsound />', {src: "good-answer.mp3"}));});
Pierre Arlaud,

37
@dirkk Non è che i browser recenti non lo supportino. È che non tutti hanno la fortuna di avere un pubblico che utilizza un browser recente.
George Reith,

14
Array.prototype.forEachitera solo su array: entrambe le funzioni di iteratore della libreria possono iterare su array o oggetti.
JoeG

3
Le funzioni sono lì per supportare i vecchi browser e per supportare il vecchio codice che chiama la libreria e il programmatore non vuole riscrivere. Anche se hai abbandonato il supporto per IE 6, probabilmente hai ancora un po 'di JavaScript in uso scritto quando hai bisogno di supportare antiche copie di IE.
Michael Shopsin

6
Molte di queste funzioni (ad es. JQuery.parseJSON ()) controllano solo se il browser lo supporta, quindi si imposta sul metodo del browser e utilizza un'alternativa solo su browser non compatibili!
Josef,

35

Perché browser diversi hanno implementazioni e funzionalità diverse integrate nel loro motore JavaScript. Lo stesso codice "vanilla-JS" potrebbe essere eseguito in modo diverso su due browser diversi o anche due versioni diverse dello stesso browser.

Lo strato di astrazione fornito dalle librerie JS popolari è un modo per aggirare questo. Dietro le quinte, funziona attorno alle diverse capacità e limitazioni dei browser e offre un'API unificata e facile da usare. Questo, a sua volta, consente operazioni comuni come ottenere un oggetto DOM o recuperare dati JSON per essere coerenti, efficienti e indipendenti dal browser.

Questo rende la vita molto più semplice per gli sviluppatori che ora possono concentrarsi su ciò che il codice dovrebbe fare, piuttosto che su come dovrebbe essere scritto per funzionare con il browser X o Y.


2
Il comportamento di "core JS" è ben specificato e testato su tutti i browser.
Domenic,

2
@Domenic Syntax a parte, le implementazioni javascript differiscono da browser a browser. Ci sono proprietà, metodi, eventi e funzionalità che troverai solo in pochi browser, o anche solo in uno a volte.
Crono,

1
Sì, i browser hanno funzionalità non standard. Ciò non ha nulla a che fare con le funzionalità standard discusse in questa domanda.
Domenic,

8
@Domenic Se per "caratteristiche standard discusse nella domanda" intendi le funzioni Array.prototype.forEache JSON.parse, una rapida ricerca su Google ti mostrerà che ti sbagli. JSONL'oggetto non era supportato su IE7 e forEachnon era definito su alcune versioni di Opera. Biblioteche come jQuery, tuttavia, erano a conoscenza di questi limiti e lavoravano attorno a loro dietro le quinte. Quindi penso che la mia risposta sia valida.
Crono,

28

1. Compatibilità con le versioni precedenti

JavaScript è un'implementazione di ECMAScript . La maggior parte di queste funzioni sono state introdotte in ECMAScript 5 (ES5), tuttavia molti browser meno recenti che hanno ancora una quota abbastanza significativa del mercato non supportano queste funzioni (vedere la tabella di compatibilità di ECMAScript 5 ), il più notevole di questi è IE8.

Generalmente le librerie torneranno all'implementazione nativa se esiste, altrimenti usano il proprio polyfill, per esempio diamo un'occhiata all'implementazione di 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;
}

Le seguenti righe verificano se il forEachmetodo esiste sull'oggetto e se è la versione di AngularJS o meno. In caso contrario utilizza la funzione già specificata (la versione nativa):

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

2. Convenienza

In JavaScript nativo Array.prototype.forEachè un metodo esclusivo di un'istanza di Array, tuttavia la maggior parte Objectè anche iterabile.

Per questo motivo molti creatori di librerie rendono polimorfiche le loro funzioni (in grado di accettare più tipi come input). Prendiamo il codice AngularJS sopra e vediamo quali input accetta:

Funzioni :

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

Array (con supporto nativo per ogni supporto):

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

Oggetti simili a array tra cui Array (senza supporto forEach nativo), String, HTMLElement, Object con proprietà lunghezza valida:

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

Oggetti:

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

Conclusione

Come puoi vedere AngularJS eseguirà l'iterazione su quasi tutti gli oggetti JavaScript, anche se funziona allo stesso modo della funzione nativa, accetta tipi di input molto più diversi e quindi è una valida aggiunta alla libreria e un modo per portare le funzioni ES5 ai browser legacy.


2
Potresti voler aggiornare il tuo link per puntare a un particolare commit (ad es. Angular.js L203-257 ) per riferimento futuro una volta mastermodificato.
Whymarrh,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.