Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I wonder why frameworks/libraries have their own helpers although they exist natively already.

Let's take jQuery and AngularJS. They have their own each iterator functions:

But we have Array.prototype.forEach.

Similarly,

But we have the JSON.parse() function in vanilla JavaScript.

share|improve this question
67  
As someone who remembers the bad old days of web development, this question makes me cry. –  josh3736 Apr 8 at 3:57
3  
@josh3736 At least you don't still have to support IE6 ('tho, luckily only in a "make it work, it can look like crap" way) –  Izkata Apr 8 at 19:16
9  
jQuery.each and Array.prototype.forEach are not equivalent. –  zzzzBov Apr 8 at 21:01
1  
What you should ask yourself is: how much of the functions found in vanillaJS now, originated from toolkits like jQ and the like? The answer is: many. This does beg the question: why are we still using them? Why include jQuery's $.each, and not use the native (and faster) Array.prototype.forEach? –  Elias Van Ootegem Apr 10 at 14:29
1  
@josh3736 It's ok bro... i.stack.imgur.com/HJs4V.jpg –  Crono Apr 10 at 18:47

3 Answers 3

up vote 89 down vote accepted

Because when those libraries were written, some major browsers did not support those features. Once written and used, these features cannot be removed from these libraries without breaking many applications.

(In this case, "major browser" means a browser that still has large market share, which includes older versions of browsers like Internet Explorer, where large number of users don't necessarily upgrade to the latest version.)

share|improve this answer
41  
$('marquee').each(function() { $(this).append($('<bgsound/>', { src: "good-answer.mp3"} )); }); –  Pierre Arlaud Apr 8 at 8:22
34  
@dirkk It's not that recent browsers don't support it. It's that not everyone is lucky enough to have an audience that uses a recent browser. –  George Reith Apr 8 at 11:17
11  
Array.prototype.forEach iterates only over arrays - both library iterator functions can iterate over arrays or object. –  Joe Gauterin Apr 8 at 12:16
3  
The functions are there to support old browsers and to support old code that calls the library and the programmer doesn't want to rewrite. Even if you've dropped support for IE 6 you probably still have some JavaScript in use written when you did need to support ancient copies of IE. –  Michael Shopsin Apr 8 at 14:19
5  
Many of this functions (e.g. jQuery.parseJSON()) just check if the browser supports it and then sets itself to the browser method, and only uses an alternative on non compatible browsers! –  Josef Apr 9 at 14:25

1. Backwards compatibility

JavaScript is an implementation of ECMAScript. Most of those functions were introduced in ECMAScript 5 (ES5) however many older browsers which still have a significant enough share of the market do not support these functions (see ECMAScript 5 compatibility table), the most notable of these being IE8.

Generally libraries will revert to the native implementation if it exists otherwise use their own polyfill, for example let's look at AngularJS's implementation (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;
}

The following lines check whether the forEach method exists on the object and whether it is the AngularJS version or not. If not it uses the already specified function (the native version):

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

2. Convenience

In native JavaScript Array.prototype.forEach is a method exclusive to an instance of Array, however most any Object is iterable too.

For this reason many library creators make their functions polymorphic (able to accept multiple types as input). Let's take the AngularJS code above and see what inputs it accepts:

Functions:

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

Arrays (with native forEach support):

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

Array-like objects including Array (without native forEach support), String, HTMLElement, Object with a valid length property:

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

Objects:

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

Conclusion

As you can see AngularJS will iterate over most any JavaScript Object, although it works in the same way as the native function it accepts far more different types of input and thus is a valid addition to the library as well as a way of bringing ES5 functions to legacy browsers.

share|improve this answer
2  
You may want to update your link to point to a particular commit (e.g. angular.js L203-257) for future reference once master changes. –  Whymarrh Apr 12 at 0:27
1  
@Whymarrh Good idea, updated it. Thanks. –  George Reith Apr 12 at 1:22

Because different browsers have different implementations and features baked in their JavaScript engine. The same "vanilla-JS" code could run differently on two different browsers, or even two different versions of the same browser.

The abstraction layer provided by popular JS libraries is a way around this. Behind the scenes, it works around the different browsers capacities and limitations and offers a unified, easy to use API on top of those. This, in turn, allows common operations such as getting a DOM object or fetching JSON data to be consistent, efficient and browser-agnostic.

This makes life a lot easier for developers who can now focus on what code should do, rather than how it should be written to work with browser X or Y.

share|improve this answer
1  
The behavior of "core JS" is well-specified and tested across all browsers. –  Domenic Apr 9 at 18:32
2  
@Domenic Syntax aside, javascript implementations do differ from browser to browser. There are properties, methods, events and features you will find in just a few browsers only, or even just in one sometimes. –  Crono Apr 9 at 18:39
1  
Yes, browsers have nonstandard features. That has nothing to do with the standard features discussed in this question. –  Domenic Apr 10 at 16:54
6  
@Domenic If by "standard features discussed in the question" you mean the Array.prototype.forEach and JSON.parse functions, a quick search on Google will show you that you are wrong. JSON object was not supported on IE7 and forEach wasn't defined on some Opera versions. Libraries such as jQuery however did knew about these limitations and worked around them behind the scenes. So I think my answer does stand. –  Crono Apr 10 at 17:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.