Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add [Symbol.iterator]() methods to NodeList, TouchList, etc. #545

Closed
kevinbarabash opened this issue Jan 20, 2015 · 16 comments
Closed

Add [Symbol.iterator]() methods to NodeList, TouchList, etc. #545

kevinbarabash opened this issue Jan 20, 2015 · 16 comments
Assignees
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@kevinbarabash
Copy link
Contributor

I was reading this MDN page on for...of: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of and they mentioned that you could use it with stuff from the DOM like NodeList. I tried it and it didn't work so I ended up polyfilling it with this code:

if (NodeList.prototype[Symbol.iterator] === undefined) {
    NodeList.prototype[Symbol.iterator] = function () {
        var i = 0;
        return {
            next: () => {
                return { done: i >= this.length, value: this.item(i++) };
            }
        }
    };
}

It actually works and lets do stuff like:

for (let { id } of document.querySelectorAll("div")) {
    console.log(`elem.id = ${id}`);
}

I'd like to create a pull request for this and the other DOM lists. Where's a good place to put browser only polyfills?

@zloirock
Copy link
Member

core-js adds only cross-platform features. You can simple add to your code

NodeList.prototype[Symbol.iterator] = [][Symbol.iterator]

@kevinbarabash
Copy link
Contributor Author

@zloirock I tried the code you posted and it works, but I don't know why. What does [][Symbol.iterator] do?

Another question: There is/was a "browser-polyfill.js" file. Would it be okay to add this code there so that everyone can use iterators with DOM lists out of the box?

@kevinbarabash
Copy link
Contributor Author

After thinking about it I realized that [][Symbol.iterator] is equivalent to Array.prototype[Symbol.iterator].

@sebmck
Copy link
Contributor

sebmck commented Jan 20, 2015

It's not the responsibility of 6to5 to polyfill this behaviour. This is better suited for core-js which is what 6to5 uses.

@sebmck sebmck closed this as completed Jan 20, 2015
@kevinbarabash
Copy link
Contributor Author

@sebmck I guess that makes sense. 6to5 is just repackaging existing polyfills. I'll create an issue with core-js and see what they say.

@kevinbarabash
Copy link
Contributor Author

@zloirock I didn't realize you were the maintainer of core-js. Is this polyfill something you'd be interested in as a optional include with core-js or should I start a separate project for stuff like this?

@fkling
Copy link
Contributor

fkling commented Jan 20, 2015

@KevinB7

What does [][Symbol.iterator] do?

It accesses the iterator method of an array. Maybe this is easer to understand:

var arr = [];
NodeList.prototype[Symbol.iterator] = arr[Symbol.iterator];
// or
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

I assume (didn't look at the code), just like other array methods, this method is agnostic and works on values that are array-like.

@zloirock
Copy link
Member

@KevinB7 As I wrote above, core-js adds only cross-platform features. You can add all of these iterators in 1 line of user code. Although as these iterators are directly related to the iterator array, I can change my position.

@gaearon
Copy link
Member

gaearon commented Jan 21, 2015

@zloirock

Just my two cents: I also assumed these would be provided by core-js. If you do decide to have them, please also include them in Nodish polyfill behind typeof checks since that's what Browserify/Webpack folks are using.

@zloirock
Copy link
Member

Show me spec, I can't find it.

@kevinbarabash
Copy link
Contributor Author

I found something in the whatwg DOM spec that mentions NodeLists having "iterable" as part of their interface in the IDL: https://dom.spec.whatwg.org/#nodelist.

@fkling
Copy link
Contributor

fkling commented Jan 21, 2015

Just to expand on the iterable<Node> declaration:

Note
In the ECMAScript language binding, an interface that is iterable will have “entries”, “keys”, “values” and @@iterator properties on its interface prototype object.

@zloirock
Copy link
Member

Ok, I will add NodeList.prototype[Symbol.iterator], but currently only it - core-js is not DOM polyfill.

zloirock added a commit to zloirock/core-js that referenced this issue Jan 21, 2015
@zloirock
Copy link
Member

Avaliable in 0.4.6.

@kevinbarabash
Copy link
Contributor Author

Thanks!

@babel-bot
Copy link
Collaborator

Comment originally made by @luxp on 2016-08-15T16:22:44.000Z

I test it in IE8, this seems not work for me.
I added babel-polyfill@6.13.0.

var nodeList = document.querySelectorAll('span');
for(let  node of nodeList) {
  node.style.color = '#DD2727';
}

And I transformed it use babeljs/repl

The result is below

'use strict';

var nodeList = document.querySelectorAll('span');

for (var _iterator = nodeList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
    var _ref;

    if (_isArray) {
        if (_i >= _iterator.length) break;
        _ref = _iterator[_i++];
    } else {
        _i = _iterator.next();
        if (_i.done) break;
        _ref = _i.value;
    }

    var node = _ref;

    node.style.color = '#DD2727';
}

But this didn't work in IE8.

You can test it using the code below

<style>
    span {
        margin-right: 10px;
    }
</style>
<script src="//cdn.bootcss.com/babel-polyfill/6.13.0/polyfill.js"></script>
<span>Rock</span><span>the</span><span>World!</span>
<script>
    'use strict';

    var nodeList = document.querySelectorAll('span');

    for (var _iterator = nodeList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
        var _ref;

        if (_isArray) {
            if (_i >= _iterator.length) break;
            _ref = _iterator[_i++];
        } else {
            _i = _iterator.next();
            if (_i.done) break;
            _ref = _i.value;
        }

        var node = _ref;

        node.style.color = '#DD2727';
    }
</script>

I found out of the problem is _iterator[Symbol.iterator]();
And I solved this problem by transfroming the nodeList to Array before using for ...of.

<style>
    span {
        margin-right: 10px;
    }
</style>
<script src="//cdn.bootcss.com/babel-polyfill/6.13.0/polyfill.js"></script>
<span>Rock</span><span>the</span><span>World!</span>
<script>
    'use strict';

    var nodeList = document.querySelectorAll('span');

   // add this line.
    nodeList = Array.prototype.slice.call(nodeList);

    for (var _iterator = nodeList, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
        var _ref;

        if (_isArray) {
            if (_i >= _iterator.length) break;
            _ref = _iterator[_i++];
        } else {
            _i = _iterator.next();
            if (_i.done) break;
            _ref = _i.value;
        }

        var node = _ref;

        node.style.color = '#DD2727';
    }
</script>

@hzoo hzoo closed this as completed Sep 8, 2016
@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label May 6, 2018
@lock lock bot locked as resolved and limited conversation to collaborators May 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

No branches or pull requests

7 participants