Por que as estruturas / bibliotecas JavaScript possuem funções que já existem em JavaScript puro?

60

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

Vamos usar jQuery e AngularJS . Eles possuem suas próprias funções each iterator:

Mas temos Array.prototype.forEach .

Da mesma forma,

Mas temos a função JSON.parse() no JavaScript do vanilla.

    
por Cihad Turhan 08.04.2014 / 01:50
fonte

3 respostas

93

Porque quando essas bibliotecas foram escritas, alguns dos principais navegadores não suportavam esses recursos. Uma vez escritos e usados, esses recursos não podem ser removidos dessas bibliotecas sem quebrar muitos aplicativos.

(Neste 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).

    
por 08.04.2014 / 01:57
fonte
35

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

A camada de abstração fornecida por 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 de navegador.

Isso torna a vida muito mais fácil para desenvolvedores que agora podem se concentrar no que o código deve fazer, em vez de como ele deve ser escrito para funcionar com o navegador X ou Y.

    
por 08.04.2014 / 02:04
fonte
27

1. Compatibilidade retroativa

O 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 têm uma fatia significativa do mercado não suportam essas funções (veja tabela de compatibilidade ECMAScript 5 ), sendo as mais notáveis o IE8.

Geralmente, as bibliotecas serão revertidas para a implementação nativa, se existirem. Caso contrário, use seu próprio polyfill, por exemplo, vamos analisar 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 método forEach existe no objeto e se é a versão do AngularJS ou não. Se não, 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 , mas a maioria dos Object também é iterável.

Por esse motivo, muitos criadores de bibliotecas tornam suas funções polimórficas (capazes de aceitar vários tipos de 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 paraEach):

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

Objetos semelhantes a matrizes incluindo Array (sem suporte nativo a for each), String, HTMLElement, Object com uma propriedade de tamanho 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 iterará praticamente qualquer objeto JavaScript, embora funcione da mesma forma que a função nativa, ele aceita muito mais tipos diferentes de entrada e, portanto, é uma adição válida à biblioteca, bem como uma maneira de trazendo funções ES5 para navegadores legados.

    
por 08.04.2014 / 13:09
fonte