# 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://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values)
* [`Set::keys`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys)
* etc...

These methods return
[`js_sys::Iterator`](https://rustwasm.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` can be converted into a Rust iterator either by reference
(into
[`js_sys::Iter<'a>`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iter.html))
or by value (into
[`js_sys::IntoIter`](https://rustwasm.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
extern crate js_sys;
extern crate wasm_bindgen;
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://rustwasm.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
extern crate js_sys;
extern crate wasm_bindgen;
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)
}
```
