Por que estruturas / bibliotecas JavaScript têm funções que já existem em JavaScript puro?


61

Eu me pergunto por que estruturas / bibliotecas têm seus próprios auxiliares, embora já existam nativamente.

Vamos usar jQuery e AngularJS . Eles têm suas próprias eachfunções de iterador:

Mas nós temos Array.prototype.forEach.

Similarmente,

Mas temos a JSON.parse()função em baunilha JavaScript.


75
Como alguém que se lembra dos velhos tempos ruins do desenvolvimento web, essa pergunta me faz chorar.
josh3736

3
@ josh3736 Pelo menos você não ainda tem que apoiar IE6 ( 'tho, felizmente apenas em um 'fazê-la funcionar, ele pode olhar como porcaria' way)
Izkata

12
jQuery.eache Array.prototype.forEachnão são equivalentes.
ZzzzBov

3
O que você deve se perguntar é: quanto das funções encontradas no vanillaJS agora são originadas de kits de ferramentas como jQ e similares? A resposta é: muitas . Isso levanta a questão: por que ainda estamos usando-os? Por que incluir jQuery $.eache não usar o nativo (e mais rápido) Array.prototype.forEach?
Elias Van Ootegem

11
@ josh3736 Está tudo bem mano ... i.stack.imgur.com/HJs4V.jpg
Crono

Respostas:


94

Porque quando essas bibliotecas foram gravadas, alguns dos principais navegadores não suportaram esses recursos. Uma vez gravados e usados, esses recursos não podem ser removidos dessas bibliotecas sem interromper muitos aplicativos.

(Nesse caso, "navegador principal" significa um navegador que ainda possui grande participação de mercado, que inclui versões mais antigas de navegadores como o Internet Explorer, onde um grande número de usuários não necessariamente atualiza para a versão mais recente.)


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

37
@dirkk Não é que navegadores recentes não o suportem. É que nem todos têm a sorte de ter um público que usa um navegador recente.
George Reith

14
Array.prototype.forEachitera apenas sobre matrizes - ambas as funções do iterador da biblioteca podem iterar sobre matrizes ou objetos.
JOEG

3
As funções existem para oferecer suporte a navegadores antigos e código antigo que chama a biblioteca e o programador não deseja reescrever. Mesmo que você tenha abandonado o suporte ao IE 6, provavelmente ainda terá algum JavaScript em uso quando necessário para suportar cópias antigas do IE.
Michael Shopsin

6
Muitas dessas funções (por exemplo, jQuery.parseJSON ()) apenas verificam se o navegador suporta e depois se ajustam ao método do navegador, e usam apenas uma alternativa em navegadores não compatíveis!
1911 Josef

35

Porque navegadores diferentes têm implementações e recursos diferentes integrados em seu mecanismo JavaScript. O mesmo código "vanilla-JS" pode ser executado de maneira diferente em dois navegadores diferentes ou mesmo em duas versões diferentes do mesmo navegador.

A camada de abstração fornecida pelas bibliotecas JS populares é uma maneira de contornar isso. Nos bastidores, ele trabalha com as diferentes capacidades e limitações dos navegadores e oferece uma API unificada e fácil de usar. Isso, por sua vez, permite que operações comuns, como obter um objeto DOM ou buscar dados JSON, sejam consistentes, eficientes e independentes do navegador.

Isso facilita muito a vida dos desenvolvedores que agora podem se concentrar no que o código deve fazer, e não na forma como ele deve ser escrito para funcionar com o navegador X ou Y.


2
O comportamento do "JS principal" é bem especificado e testado em todos os navegadores.
Domenic

2
@Domenic Syntax à parte, as implementações de javascript diferem de navegador para navegador. Existem propriedades, métodos, eventos e recursos que você encontrará em apenas alguns navegadores, ou mesmo apenas em um, às vezes.
Crono

11
Sim, os navegadores possuem recursos não padrão. Isso não tem nada a ver com os recursos padrão discutidos nesta pergunta.
Domenic

8
@Domenic Se por "recursos padrão discutidos na pergunta" você se refere às funções Array.prototype.forEache JSON.parse, uma rápida pesquisa no Google mostra que você está errado. JSONO objeto não era suportado no IE7 e forEachnão estava definido em algumas versões do Opera. Bibliotecas como o jQuery, porém, conheciam essas limitações e as contornavam nos bastidores. Então, acho que minha resposta permanece.
Crono

28

1. Compatibilidade com versões anteriores

JavaScript é uma implementação do ECMAScript . A maioria dessas funções foi introduzida no ECMAScript 5 (ES5); no entanto, muitos navegadores mais antigos que ainda possuem uma participação significativa no mercado não suportam essas funções (consulte a tabela de compatibilidade do ECMAScript 5 ), sendo o IE8 o mais notável.

Geralmente as bibliotecas reverterão para a implementação nativa, se existir, caso contrário, use seu próprio polyfill; por exemplo, vejamos a implementação do 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;
}

As linhas a seguir verificam se o forEachmétodo existe no objeto e se é a versão do AngularJS ou não. Caso contrário, ele usa a função já especificada (a versão nativa):

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

2. Conveniência

No JavaScript nativo, Array.prototype.forEaché um método exclusivo para uma instância de Array, no entanto, quase todos também Objectsão iteráveis.

Por esse motivo, muitos criadores de bibliotecas tornam suas funções polimórficas (capazes de aceitar vários tipos como entrada). Vamos pegar o código AngularJS acima e ver quais entradas ele aceita:

Funções :

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

Matrizes (com suporte nativo para cada um):

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

Objetos semelhantes a matrizes, incluindo Matriz (sem suporte nativo para Cada), String, HTMLElement, Objeto com uma propriedade de comprimento 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);
    }
  }
}

Conclusão

Como você pode ver, o AngularJS itera sobre a maioria dos objetos JavaScript, embora funcione da mesma maneira que a função nativa, aceita tipos de entrada muito mais diferentes e, portanto, é uma adição válida à biblioteca e também uma maneira de trazer funções ES5 para navegadores herdados.


2
Você pode atualizar seu link para apontar para um commit específico (por exemplo, angular.js L203-257 ) para referência futura, uma vez que as masteralterações sejam alteradas.
Whymarrh
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.