[].slice.call() pattern in javascript [duplicate] - javascript

This question already has answers here:
Explanation of [].slice.call in javascript?
(9 answers)
Closed 1 year ago.
Bootstrap 5 Javascript examples sometimes show code like:
var collapseElementList = [].slice.call(document.querySelectorAll('.collapse'))
Why isn't this just:
var collapseElementList = document.querySelectorAll('.collapse')
What is [].slice.call() doing exactly? I don't understand why you'd slice on an empty array, and then I have no idea what call is doing there. What would be the problem with the obvious way to do this, the second way above?

querySelectorAll returns a NodeList, which is a collection, but not an array.
[].slice.call turns an array-like collection into an array proper. It will allow you to use array methodss on it, eg:
var collapseElementList = [].slice.call(document.querySelectorAll('.collapse'));
const textsOfCollapsedElements = collapseElementList.map(elm => elm.textContent);
Otherwise, if you don't convert it to an array first, you won't be able to use array methods on it.
It's probably most important for forEach. Newer browsers support NodeList.prototype.forEach, but it hasn't been with us that long. In contrast, Array.prototype.forEach has existed forever. So turning the collection into an array allows for forEach to be called on it, even on obsolete browsers that don't support NodeList.prototype.forEach.

It's an idiom for turning anything array-ish (in this case a DOM NodeList) into a real Array by exploiting the fact that Array::slice can work on anything that's iterable and has a .length property.
The modern idiom is Array.from(...).

Related

what is at() method in JavaScript? [duplicate]

This question already has answers here:
Using Array.at(index) instead of Array[index] in JavaScript
(4 answers)
Closed last year.
Array.prototype.at()
what is .at() method in JavaScript?
const myList = ['index0', 'index1', 'index2']
myList.at(1) // 'index1'
mylist.at(-1) // 'index2'
there are many methods in js that similarly do this, why using this new method?
Yes, there are similar ways to get an element from an array or string, but at() will use a clear and easy syntax to get this.
give an index and return value
the principle is easy, just put your desire index and get value, if there isn't a value at this index, it returns undefined
for examples:
const myList = ['index0', 'index1', 'index2']
// to get latest item in the list using common ways:
const latestItem = myList[ myList.length - 1]
// using simpler approach with at()
const latestItem = myList.at(-1)
similarly, at() method will work fine with strings.
at the writing time of this post, at() will not be supported by some browser, you can find this here.
you can use polyfill if you want to use at() method in your codebase.

What is the difference between Array.from(Object) and [...Object]? [duplicate]

This question already has answers here:
Array.from() vs spread syntax
(6 answers)
Closed 3 years ago.
There are these two ES6-methods of creating an array from an array-like or iterable object:
Array.from(): let arr = Array.from(Object);
Spread syntax: let arr = [...Object];
Here are both in action doing exactly the same:
let string = 'foobar';
console.log( [...string] );
console.log( Array.from(string) );
What is the difference between the two and which one should I use preferably to convert a HTMLCollection to an array?
Update for 2022
Most of us don't have to support IE anymore, and it matters a lot less which one you use than it used to because there's less potential for the kind of bug I describe below to slip through to production.
Original answer
There isn't much difference in terms of what each does (except in a few contrived scenarios), but you should almost certainly use the spread syntax. The reason is that syntax will automatically be converted by babel, the Typescript compiler, etc. but you'll need to add a polyfill for Array.from unless you just don't care about older browsers. In general prefer compile/build-time solutions to run-time solutions.
Spread syntax only works with objects that implement the iterator method (Symbol.iterator()).
Array.from() on the other hand will also work on array-like objects(indexed elements) which do not implement the iterable method.
Array.from() can be used for HTML collections because of the readability as the results for both will be same in this case.

JavaScript iterate through NodeList [duplicate]

This question already has answers here:
Why doesn't nodelist have forEach?
(11 answers)
Looping through a nodelist JS
(1 answer)
Closed 3 years ago.
I am looking for a best way to iterate through NodeList excluding length. I am using:
var foo = document.querySelectorAll('[id^=foo_id]')
console.log(foo)
Returned NodeList has all the required elements + the last entry of length:.
0: input#foo_id_...
1: input#foo_id_...
..................
n: input#foo_id_...
length: n+1
I wonder what the most efficient way to iterate through that NodeList. I can utilize list length etc, but would like to know if there is a more "elegant" way.
The simplest way is a for loop:
for (let i = 0; i < foo.length; i++) {
// Do stuff
}
This is the best solution, as pointed out here it's bad practice to use array methods or convert a NodeList to an array - use a different variable if you need to, but a for loop is all you need to loop over a NodeList. (Thanks Heretic Monkey for pointing this out to me).
If you want to use array methods like forEach, map, etc., it's best convert to an array first - this is incredibly simple with spreading:
[...foo].forEach(e /* Do stuff */);
If you want to specifically use map, use Array.from as the second argument is the callback to be applied to map.
Array.from(foo, e => /* .map callback */);
And in older environments:
Array.prototype.slice.call(foo).forEach(e => /* Do stuff */);
(I know that you can use array methods on a NodeList, but it's easier if you stick to using one data type.)
Although NodeList is not an Array, it is possible to iterate over it with forEach()
See also Why doesn't nodelist have forEach?

addEventListener is not a function simple code pasted from Khan ACA [duplicate]

This question already has answers here:
What do querySelectorAll and getElementsBy* methods return?
(12 answers)
Closed 4 years ago.
Screenshot
Im a begginer of Javascript and its a bit obvious what im trying to do, its a simple code but it tells me always 2 things, addEventListenerenter code here` is not a function" and "add event listener undefined" tried Loops, tried changing Elements for Element tried telling which from the elements is fromm [number (i know first is cero)], changed place of script, and tried giving boolean values to face, Help.
Don't paste screenshots of code, paste your actual code instead.
The problem is that getElementsByClassName returns an HTMLCollection, not a single element, so you can't assign a listener to the collection: select a single element first.
The getElementsBy* methods return HTMLCollections, which can be difficult to work with. Consider using querySelectorAll instead, which returns a static NodeList - unlike an HTMLCollection, it can be iterated over directly, it won't change while it's being iterated over, and it's much more flexible.
Try something like this:
document.querySelectorAll('.alex').forEach((alex) => {
alex.addEventListener('mousemove', () => document.querySelector('.pipo').textContent += 'mooove';
});
Note that NodeList.forEach is something new-ish, supported as of the past few years - to support ancient browsers, use a plain for loop or a polyfill. (array methods are generally superior to for loops: no manual iteration, better abstraction, function parameters)

Optimal way of determining array type [duplicate]

This question already has answers here:
JavaScript way to tell if an object is an Array [duplicate]
(6 answers)
Closed 7 years ago.
What is the best way to determining the object type is Array and why?.
var arr = [];
// Method #1
Array.isArray(arr);
// Method #2
toString.call(arr) == "[object Array]"
// Method #3
arr.constructor == Array
All three methods can be used to test if variable is of Array type. However, there are some nuances. I will start from the last to first.
Method #3. Will not work if variable in question came from other winndow/frame. In this case, constructor will point the the different Array object and this check will return false. For the same reason, arr instanceof Array is not bullet-proof. So it's not 100% reliable.
Method #2. This is the method that has been traditionally used to verify array type. In fact, Array.isArray polyfill is based on this method. The only disadvantage is that it's cumbersome and verbose.
Method #1. Is the one from ES5 that should finally be used to test array type, no matter what realm array comes from (like iframe). This is is the best in the list.
The prefered method is to use Array.isArray. This is present in the ES5 language specification and quite well supported by the browsers.
If you plan to support old browsers, You can find a polyfill on MDN. The polyfill is basically your second option.
The last option will not work if you play with iframes.
var arr = myIframe.contentWindow.myArray;
console.log(obj.constructor === Array); //false
The reason is that the Array constructor is diffferent for each window object. Using this to detect arrays will work 99% of the time but will suddenly fail one day.

Categories