What is the most performance effective foreach loop in JS with returning index?
best loading times have:
but how can I get index of each loop?
spacecrafts.forEach(function(spacecraft) {
// how can i call index without calling prototype and only with anonymous function?
console.log(index,spacecraft);
});
Like ShanShan said in the comment, the index is the second parameter of the anonymous function being passed to forEach. The code would look like this.
spacecrafts.forEach(function(spacecraft, index) {
console.log(index,spacecraft);
});
If for some reason you really need performance, go ahead and use BenchmarkJs to test your particular use cases and find what is fastest. In general, the built-in Array prototype functions aren't as performant as a basic for-loop. You might want to look into using a library like lodash, or underscore which say they try and be performant.
Related
In the last year I've been using array methods like map and filter more often instead of the standard for loop on an array. It feels simpler to read and write, and does all the things I'm most likely going to do anyway, like create a local variable.
Often times I don't return anything though. Eslint doesn't like me very much though. According to them, they say you always need a return, otherwise its "probably a mistake"
https://eslint.org/docs/rules/array-callback-return
Why? Is just good practice? What are downsides of a return-less array method?
Been thinking on this for a while. Any insight or thoughts would be great.
Should I use array methods like map and filter, if I'm not going to return anything?
No, you should not.
Why? Is just good practice?
Yes. It is a good practice to use the appropriate iteration method for the type of iteration you are doing. There are numerous ways to iterate for a reason. Pick the appropriate mechanism.
What are downsides of a return-less array method?
Using .map() and .filter() without actually returning anything from the callback have the following downsides:
Your code is misleading. The point of .map() and .filter() is to iterate over the array and produce a new array. When a developer reads some code and sees .map() or .filter() being used, they expect that there should be a returned array. When they don't see it being done that way, they will be confused, will initially feel like they don't understand the code. If I were doing a code review on code like this, I would not approve of code like this.
Your code unnecessarily creates objects that are not used. That's just wasteful and is not a good practice. Instead, use an iteration method that does not produce an output array such as for/of, a regular for loop or .forEach().
Your code won't lint. Linters provide objections to things for a reason. Using .map() or .filter() without returning anything from the callback is, just as the linter says, "probably a programming mistake" because that is not how those functions are designed to be used and there are appropriate alternatives when you don't want a returned array.
So, if you're just trying to do an iteration without creating any resulting array, use for/of or .forEach() or some other iteration scheme that isn't specifically designed to create an output array that you don't want.
First you need to know about the difference between Map/Filter and forEach.
resuming.. forEach is mostly used when you want iterate an array with/as a procedure. check
Map and Filter are related to a callback function applied on every iteration.
The return statement of those is what is going to be evaluated, not the function By the Map/Filter function at the end. Reason why it's needed. Althought JS allows "whatever" And of course you are able to define that function what comes to our understanding as "The filter".
For Filter you can see that "true" and "false" as when the "data" is going to be filtered or not.
basically you can loop with map or forEach/for, the difference are the following:
foreach: This iterates over a list and applies some operation with side effects to each list member, this means that you are transforming THE CURRENT ARRAY you are looping.... or as noticed by #TiagoCoelho, you dont mess with the array at all, just loop thought it.
map: This iterates over a list, transforms each member of that list, and returns another list of the same size with the transformed members, this means that you will get a BRAND NEW ARRAY with the modified items and you will also have in memory your old array.
so basically it depends on what you want to do with the data inside of your array.
References
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
examples:
var a = [1, 2, 3, 4];
var b = [1, 2, 3, 4];
//multiply each item for 2, it will stay on the same array.
a.forEach(i => {
i = i * 2
})
//multiply the items of B for 2 but it will return a new array
var c = b.map(i => {
return i * 2
})
console.log(a); //modified reference
console.log(b); //stays the same
console.log(c); //new array
Just wondering what's the different with the following js script.
[].slice.call(this) vs Array.prototype.slice.call(this);
They seems to be doing this same, can someone explain the different and which one i should stick with?
Cheers
They are almost identical. Let's examine each of them:
[].slice.call(data)
What it does?
[] - this creates new Array, same to new Array()
slice - it retrieves method slice from array
call(data) - it calls slice() method replacing its current context with data variable, i.e. uses data as its internal array, not []. This returns our data converted into Array.
Now, the second one:
Array.prototype.slice.call(data)
This one:
Array.prototype.slice - retrieves method slice from Array.prototype; in a nutshell - it returns you slice method without any context (internal data).
call(data) - as in previous variant, calls this method with data as its context.
Conclusion
Both [].slice and Array.prototype.slice return you a slice function which you can call on some array, however this array is passed not as argument, but as context (using call method of function object). In JavaScript, these calls will be absolutely the same:
// Calling as a method of 'Hello' string
'Hello'.indexOf('e') // returns 1
// Calling as unbound method
String.prototype.indexOf.call('Hello', 'e') // returns 1
String.prototype.indexOf.apply('Hello', ['e']) // returns 1
Those methods are almost the same. First one is more readable, but second one uses a bit less memory because it isn't creating a temporary initial Array.
I believe that Array doesn't actually create an object, where as [] is an instance of Array.
Definitely stick with the latter one as the first one is an implicit array construction and the same as:
new Array().slice.call(this)
Its constructing a new array that needs to be garbage collected afterwards since you dont use it. While both statements "work", the above mentioned does a lot of extra work, first you construct a new instance, then you look up if the instance itself has a slice property, as this is false the prototype chain is traversed and the slice is found on the Array.prototype and then called. Then you call it with your other array as scope, so essentially render the instance you created useless by using your other one.
Thats why Array.prototype.slice.call(myarr) is the proper way of accessing the slice method.
Array.prototype.slice.call() seems slightly more performant, though that makes sense because it would be quicker at runtime to "look up" this method. I posit that [].slice.call() is the best choice. Here's the jsperf of reference
Let's be real, in what case would the negligible difference between the two be a major contributor to poor website performance? sounds like heaven, actually. The shorter syntax of the literal method is awesome. I'd rather save myself the half-second it'd take to type the prototype variant than be shakily more efficient.
The coffin nail of Array.prototype... some people say is that it's irresponsible because you risk altering it. But... that's stupid. Figure 1: Array.prototype = function() { console.log('foo') }; Whoopsie... That probably happens all of the time. Seriously, even granting its legitimacy is still intact, it takes me longer to type and is imo hideous compared to its sexier literal sister.
The real answer to your real question is that the functionality is exactly the same. Use whichever you will still appreciate on your deathbed.
I'm currently use jquery 1.8.3. I think it added indexOf to Array.prototype so now every of my array always contains the method indexOf as the first element.
Doing for (var i in object) I always get the method infexOf as my first element and it bugged my code.
Bug happened on IE8 only.
What I want is to remove this indexOf from all arrays or anyway to hack jquery / resolve this problem.
PS: I'm not even sure if it's jquery is the cause of this problem
Thanks.
Aside from not using for...in to iterate over an array, if you must use for...in, then combine it with hasOwnProperty to tell if the property you are looking at really belongs to the object in question, or came from the prototype:
for (var prop in myObject) {
if (myObject.hasOwnProperty(prop)) {
// this didn't come from the prototype.
}
}
The correct answer here is that you shouldn't be using a for(...in...) loop to iterate an Array in Javascript.
The whole point of having an Array is that it has a numbered sequence of elements, so you should be using a for() loop.
for(var i=0; i<myArray.length; i++) {
//do stuff here with myArray[i]
}
That alone will resolve the issue in this case, because it will only iterate the numbered elements, so the indexOf method won't get involved.
However, a brief explaination of the problem with for(..in..) here may be helpful, so let me explain...
The underlying cause of the error you're seeing is because the indexOf method isn't supported for arrays in IE8, so something in your code (not jQuery though) has added it to the Array prototype.
This in turn means that when you do a for(..in..) loop, it will be picked up as one of the elements to be iterated.
In this case, you have a better solution (the for() loop; see above), but in cases where you really do need to use a for(..in..) loop, this can be a real problem. You can prevent this by checking hasOwnProperty() immediately inside your for(..in..) loop. This function returns false for items that are part of the object prototype, so it helps you avoid hitting unwanted methods when looping an object.
This is considered best practice for every for(..in..) loop. In fact, if you use a tool like JSLint, to check your coding style, it will complain if you don't do this.
I've been working in backbone.js and came across the following snippet of code.
_(view.buttonViews).each(function(button) {
button.render();
});
Where view.buttonViews is an array. If I take away the _() and have
view.buttonViews.each(function(button) {
button.render();
});
then I get an error that each is not a function. What does the _() add? Thanks!
I guess it is the Underscore.js library which provides the each method:
_.each(list, iterator, [context]) Alias: forEach
Iterates over a list of elements, yielding each in turn to an iterator function. The iterator is bound to the context object, if one is passed. Each invocation of iterator is called with three arguments: (element, index, list). If list is a JavaScript object, iterator's arguments will be (value, key, list). Delegates to the native forEach function if it exists.
This way, _([...]).each(...), is just another way of calling it.
BTW, it is also described in Backbone's documentation:
Backbone's only hard dependency is Underscore.js.
And FWIW, as #Jonathon already said, in general, _ is a valid variable name and in this case it contains a function. Adding parenthesis behind a function references calls that function and therefore, _() calls the function referred to by _. It is nothing special.
Besides that, parenthesis can occur as part of a function declaration or expression (function foo() {...}) or as grouping operator (var i = (20 + 1) * 2;).
Backbone is built on top of underscore, a utility library providing a lot of useful functionality that isn't native to JS but probably should be (eg things like traversing objects, array mapping, eliminating duplicate items in an array, that sort of thing).
It can be written using object-oriented or a functional style. So for instance your snippet of code could also be written thus:
_.each(view.buttonViews,function(button) {
button.render();
});
Backbone depends on Underscore which implements many utility functions. You can wrap an array with the _() function and use the Underscore API as demonstrated here.
Underscore implements these functions without touching the prototype, so each is not available to a regular array. However, it is callable from the object returned from the _ function, which wraps the original array.
Backbone provides functions from Underscore.js -> http://documentcloud.github.com/backbone/#Collection-Underscore-Methods
Pouring over the release notes regarding jQuery 1.4, I came acrosss $.noop() which is:
Description: An empty function. (added in 1.4)
You can use this empty function when you wish to pass around a function that will do nothing.
Perhaps I'm missing something profound here, but what exactly is a practical use of passing around an empty function?
Code examples appreciated.
This function was proposed due to performance issues on embedded systems when using $.ajax, reported on the jQuery-Dev mailing list. You can see the thread.
Basically, they preferred to introduce and use this single empty function, rather than declaring empty anonymous functions all around.
Now this function is internally used in the ajax, event and offset modules.
You can give a look to the commit when it was introduced also.
If you have a function that accepts a function as a parameter, and you don't have any code to give it, you can pass $.noop.
I can't think of any such cases in jQuery where the parameter isn't optional in the first place, though.
Unlike writing function(){}, passing $.noop will not create a new function instance, saving a bit of memory. However, if whatever you're passing it to modifies the function object (eg, funcParam.id = 2), passing $.noop will mess things up.
Real World Example (well almost):
jQuery.fn.myAwesomeAjax = function(url, complete) {
return jQuery.ajax(url || this.url)
.complete(complete || jQuery.noop);
};
Use it instead of function (){}
Probably if some bad API requires a function as a parameter, and you don't want to do anything in it, this would be a framework-supported way of making that obvious.
I use a couple of plugins which require callbacks, but for some parts I don't actually want to use a certain callback. So, I put in function() {}.
noop is defined in the jQuery source as
noop: function() {}
so it will fit anywhere you'd use a blank function, such as the above example.
The only logical reason is if you're calling a function that does something AND calls another function, and you want the higher-level function to do its thing without calling a parameter function.
Most of the jQuery functions optionally take a parameter function, so you don't have to pass one in. Maybe there's one or two where that's not the case -- or maybe it's to assist developers with their custom code that behaves like this.
If a function requires you pass a function as an argument maybe? It's shorter to say do_something($.noop) than do_something(function(){}).
Although not by much...
...6 characters...
...yeah, that feature looks quite useless actually.
It can be useful if you have a function that supplies functions to other functions.
Example: You have a List of data. Each item has a Button that does something. The "something" can be different for every item. You have a "FunctionFactory" that takes in the item and returns a function. If you don't want the button to do something for whatever reason, then the cleanest way could be to return an empty function, as that way you know that your Factory ALWAYS returns a function.
I don't have a concrete example for jQuery, but I guess this could come in handy when used in an .each or .map block.
It's purely a convenience/replacement for function(){} in the context of where callbacks are required - I don't think I'll be using it anytime soon.
I bet the jQuery team had quite a laugh when they dropped it in though, also serves a comedic purpose.