# Iterating over JavaScript Values

## Methods That Return `js_sys::Iterator`

Some JavaScript collections have methods for iterating over their values or
keys:

* [`Map::values`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values)
* [`Set::keys`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys)
* etc...

These methods return
[`js_sys::Iterator`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.Iterator.html),
which is the Rust representation of a JavaScript object that has a `next` method
that either returns the next item in the iteration, notes that iteration has
completed, or throws an error. That is, `js_sys::Iterator` represents an object
that implements [the duck-typed JavaScript iteration
protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).

`js_sys::Iterator` and `js_sys::AsyncIterator` also support [erasable generic type parameters](./types/js-sys.md) like `Iterator<T>` and `AsyncIterator<T>`, allowing you to document the expected type of values yielded by the iterator. The generic type is erased at the ABI boundary, but provides type safety and documentation in your Rust code.

`js_sys::Iterator` can be converted into a Rust iterator either by reference
(into
[`js_sys::Iter<'a>`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.Iter.html))
or by value (into
[`js_sys::IntoIter`](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/struct.IntoIter.html)). The
Rust iterator will yield items of type `Result<JsValue>`. If it yields an
`Ok(...)`, then the JS iterator protocol returned an element. If it yields an
`Err(...)`, then the JS iterator protocol threw an exception.

```rust
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn count_strings_in_set(set: &js_sys::Set) -> u32 {
    let mut count = 0;

    // Call `keys` to get an iterator over the set's elements. Because this is
    // in a `for ... in ...` loop, Rust will automatically call its
    // `IntoIterator` trait implementation to convert it into a Rust iterator.
    for x in set.keys() {
        // We know the built-in iterator for set elements won't throw
        // exceptions, so just unwrap the element. If this was an untrusted
        // iterator, we might want to explicitly handle the case where it throws
        // an exception instead of returning a `{ value, done }` object.
        let x = x.unwrap();

        // If `x` is a string, increment our count of strings in the set!
        if x.is_string() {
            count += 1;
        }
    }

    count
}
```

## Iterating Over <u>Any</u> JavaScript Object that Implements the Iterator Protocol

You could manually test for whether an object implements JS's duck-typed
iterator protocol, and if so, convert it into a `js_sys::Iterator` that you can
finally iterate over. You don't need to do this by-hand, however, since we
bundled this up as [the `js_sys::try_iter`
function!](https://wasm-bindgen.github.io/wasm-bindgen/api/js_sys/fn.try_iter.html)

For example, we can write a function that collects the numbers from any JS
iterable and returns them as an `Array`:

```rust
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn collect_numbers(some_iterable: &JsValue) -> Result<js_sys::Array, JsValue> {
    let nums = js_sys::Array::new();

    let iterator = js_sys::try_iter(some_iterable)?.ok_or_else(|| {
        "need to pass iterable JS values!"
    })?;

    for x in iterator {
        // If the iterator's `next` method throws an error, propagate it
        // up to the caller.
        let x = x?;

        // If `x` is a number, add it to our array of numbers!
        if x.as_f64().is_some() {
            nums.push(&x);
        }
    }

    Ok(nums)
}
```
