I am writing an Array-derived class in JavaScript and need to know which functions to overload so that I can be aware of changes made to the array.
I know Array.push() and Array.splice() are mutating. Is there a definitive list of any others?
You can find the list on MDN as Mutator methods (along with Accessor and Iteration methods):
copyWithin
fill
pop
push
reverse
shift
sort
splice
unshift
You can also use .concat(), before using your mutation method, to ensure you are not mutating your arrays, eg
const dontMutateMe = [4,5,1,2,3];
const sortArray = dontMutateMe.concat().sort(...)
I found this website called Doesitmutate
Have the list of all functions - and tells whether it mutates or not.
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
There are a few loops in javascript including forEach, some, map, and reduce. However, from what I currently understand, none of these are appropriate if you want to iterate through an array and return the value of a particular index. It seems like I am pretty much left with the standard for loop only. Is that true?
So for instance, if I have an array of objects... and I would like to find the index of the item with a particular value... could I use anything other than the regular for loop?
Array.prototype.findIndex() , as suggested by #Andreas in comments.
You can pass in a function to findIndex() method and define your equality criteria in that function.
It will return the index of first array element, that satisfies the equality criteria defined in your function.
There is also the for ... of ...:
for (variable of iterable) {
statement
}
You can use a JavaScript library http://underscorejs.org. It have plenty of functions. for your purpose you can use _.indexOf . it will eturns the index at which value can be found in the array
example:
var data=[1, 2, 3];
var index= _.indexOf(data, 2);
out put will be 1
Array.prototype.findIndex() or Array.prototype.indexOf() like everyone said.
You could use foreach() rather than regular for.It is the simplest and you can iterate and get the index. For more info: JavaScript Array forEach() Method
One of my friends uses [].slice.call() to fill an array with matched elements.
I wonder how this works. I just know the Array.prototype.push to fill an array.
Also I have seen there is a difference in both techniques to fill an array.
So my questions are:
How does Array.prototype.slice help to fill an array?
What are the roles of Array.prototype.slice and Array.prototype.push to make objects and arrays?
Fiddle
var arr=[];
var arr=[].slice.call($('[id^=name]'));
//arr.push($('[id^=name]'))
console.log(arr)
The .slice() method of arrays returns a shallow copy of a portion of an array. It's written as a method on the Array prototype, so the array it operates on is the array in whose context it's invoked. Normally that'd be something like this:
var newArray = oldArray.slice(2, 4);
When you call the .slice() method with .call(), you can control the value of this explicitly. In your friend's code, he's passing a jQuery object as the this value. Because there are no other parameters, .slice() returns a shallow copy of the jQuery object in its entirety, as a new array. (Like some other similar methods, .slice() will work on anything that looks like an array: basically, anything that has a .length property and numerically-indexed properties of interest. A jQuery object fits that description.)
However, since jQuery already has a built-in method to return a plain array of all matched elements, your friend should not bother doing that anymore:
var plainArray = $('[id^=name]').get();
That does exactly the same thing. Using .slice() isn't wrong, but it's kind-of pointless.
How about $('[id^=name]').get()?
The [].slice.call method leverages the array-like length and numeric key properties of jQuery objects to re-use the intentionally generic methods of Array.prototype. The method Array.prototype.slice is documented by the standard to return a new Array object by performing a specific algorithm that accesses numeric-keyed properties in sequence of the this object - regardless of its type - assigning the values to sequential elements of the new Array.
I wouldn't use either approach, because jQuery has get(), which is documented to return an array of the elements matched. Why use a more obscure or less direct approach?
I does't have any specified reason for this case, but The thing i know is, .slice() also used to create another instance of an array, And here the slice add a space to its instance because it have no parameters.
Javascript is the language where you perform a Single operations in 1000's of different ways ! its depend on your choice!
But, We must have to follow the syntax that is made for particular operation.
I want to use filterFilter functionality but I want to reuse the arrays of data instead of creating a new array everytime it runs. So returning an array of indexes and then I can, inside my service, return the items associated to the indexes. This way I can create a $watch export on my service, so I can watch on the real items instead of the filters.
I considered copying the angular filterFilter source, but that isn't maintainable in the long run, what could I do?
Context:
I'm writing a form wizard service that applies a schema to the steps (there are many with slightly different object structures each step), that holds an array of objects. filterFilter returns a new array of objects, so when I modify the object inside the service using a "setter", it's not updating the object itself, but a new (?) created object, and that's no use for me
Javascript has Object.keys( arrayName ) to do just that, but you'll have to include a poly-fill for IE8 or lower.
var a = ['foo', 'bar'];
Object.keys( a ); //returns ['0','1'];
The MDN Object.keys article has an article for implementation if you want to use this with older browsers.
However, upon looking at your problem I think you misread the filter filter. When you use this filter it may return a different array than the input, however every object in that filter is still a reference to an object in the original. So editing any object should modify the original without a problem.
Hope this helps.
var c=$('<canvas></canvas>')[0].getContext('2d')
for(m in c){console.log(m)}
This prints a list of methods in CanvasRenderingContext2D. How can I do the same for an Array. I want to get "splice", "pop", "push", etc. Obviously for(m in Array.prototype){console.log(m)} won't work.
Most methods and properties of built-in objects are internally marked as non-enumerable, so they will not be enumerated in a for-in loop.
ECMAScript 5 has an Object.getOwnPropertyNames method that returns an array of all property names, so you can do:
Object.getOwnPropertyNames(Array.prototype)
but this isn't supported by all browsers yet.
Do this:
for (m in Array) {
console.log(m)
}
Output:
from
type
implement
extend
alias
mirror
$family
$constructor
pop
push
reverse
shift
sort
splice
unshift
concat
join
slice
indexOf
lastIndexOf
filter
forEach
every
map
some
reduce
reduceRight
each
clone
invoke
clean
associate
link
contains
append
getLast
getRandom
include
combine
erase
empty
flatten
pick
hexToRgb
rgbToHex
overloadSetter
overloadGetter
hide
protect
apply
call
attempt
pass
delay
periodical
create
bind
bindWithEvent
run
I have no idea how to do it with plain js. I usually have underscorejs loaded ant it have an it have a function that returns all the functions of an object
http://documentcloud.github.com/underscore/#functions
You could check underscorejs code to check how they do it.