5

I've just been looking over some photos from this year's ng-europe conference and noticed a slide I think might show some code from the upcoming Angular 2. See here:

Example from ng-europe

(Source: https://plus.google.com/u/0/photos/+ThierryLAU/albums/6073085583895256529/6073092865671487010?pid=6073092865671487010&oid=105910465983441810901)

What I don't get is this:

Why is the author of this code using Array.prototype.forEach.call(array, cb) in preference to the shorter and (in my opinion) equivalent version array.forEach(cb). The only reason I could imagine would be performance implications.

Does anybody know of another difference? Or am I maybe right with my performance guess?

3
  • possible duplicate of JS - Why use Prototype? Commented Oct 24, 2014 at 10:48
  • The main reason why [].forEach.call(arr) is used is to prevent array-like objects (arguments object, DOM node lists, etc.) throwing an error because Array.prototype is not in the prototype chain of those objects. Here's a very similar question, but asked from the other side: stackoverflow.com/questions/1424710/… Commented Oct 24, 2014 at 10:56
  • @Qantas. Thanks for the answer. But why did you leave it as a comment instead of an answer? Commented Oct 24, 2014 at 11:52

2 Answers 2

8

There are number of Array-like objects which look like arrays, however are not. To name some:

  • arguments
  • children and childNodes collections
  • NodeList collections returned by methods like document.getElementsByClassName and document.querySelectorAll
  • jQuery collections
  • and even strings.

Many array prototype methods are generic by purpose, which means that their internal implementation does not depend on context this to be an instance of Array constructor. This allows to call those methods in the context of other objects which "look" like arrays. Namely, looking like an array means that the object have numeric keys and length property.

Here is one useless example of how you can call Array.prototype.join on custom array-like object:

Array.prototype.join.call({0: 'one', 1: 'two', length: 2}, ' ');

Above will output string "one two". However supplied object is clearly not an array.

Sign up to request clarification or add additional context in comments.

3 Comments

but why does it still working if we pass as this the window? Is it Array-like object? For example: Array.prototype.forEach.call( window, function( element, index, array ){ console.log(index, element, array) })
@Sotiris Generally what you posted will not work on any page. I assume since it worked for you, you tested this script on the page with frames, am I right? One more time: to be an array-like object object must have length property and numeric keys: 0, 1, etc. If the document has frames then window.length show how many of them and window[0], window[1], etc. reference those frames/iframes in order they appear in document. So in this case window object indeed becomes array-like, because it allows access to some properties by numeric indexes and also has length property.
thank you very much for the insight. Indeed it was the iframes of some plugins. Testing it on incognito returns undefined as expected.
1

It is being a bit defensive against element.attributes or element.children not being arrays.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.