admin管理员组文章数量:1334887
Element.prototype.each = function(fn) {
for(var i = 0; i < this.length; i++) {
fn(i);
}
};
var li = document.getElementsByTagName('li');
li.each(function(i) {
this.style.borderBottom = '1px solid red';
});
I'm trying to make an each method like in jQuery. I tried many things in the for loop and in the callback but I got errors. I'm sure this is something to do with the 'this' context.
Element.prototype.each = function(fn) {
for(var i = 0; i < this.length; i++) {
fn(i);
}
};
var li = document.getElementsByTagName('li');
li.each(function(i) {
this.style.borderBottom = '1px solid red';
});
I'm trying to make an each method like in jQuery. I tried many things in the for loop and in the callback but I got errors. I'm sure this is something to do with the 'this' context.
Share Improve this question asked Dec 18, 2014 at 10:39 Victor RicoVictor Rico 834 bronze badges3 Answers
Reset to default 8You can use call to set context
EDIT : Element
was not the right class, it should be NodeList
and HTMLCollection
NodeList.prototype.each = HTMLCollection.prototype.each = function(fn) {
for(var i = 0; i < this.length; i++) {
fn.call(this, i);
}
};
When you use Function.prototype.call
it allows you to bind a context AKA this
to a function
There are 3 ways AFAIK to do this:
- call (as said above)
- apply (which works like call except it takes only two arguments, the second being an array)
- bind (which is used for currying)
Also note that as of DOM level 4 (ES6 harmony) there is a new class called Elements
which extends Array
and is meant to replace NodeList
/HTMLCollection
, so you wouldn't need to actually extend it in ES6 to add an each
method and use Array.prototype.forEach
instead (though you won't be able to use this
in your callback.
document.getElementsByTagName('li')
returns HTML Collection
object, not Element
.
It's quite easy to duplicate jQuery each
(the only difference between native forEach
and $.each
is order of parameters - $.each
uses (i,el)
tuple, [].forEach
uses (el,i)
tuple). In modern browsers (all except IE8) you can just use:
document.getElementsByTagName('li').constructor.prototype.each = function(fn,thisArg) {
[].forEach.call(this, function(el,i,array) {
fn.call(thisArg, i,el,array);
});
};
I don't remend to extend native prototypes, you should use [].forEach.call(yourNodeList, func)
instead. It's possible to do yourNodeList = [].slice.call(yourNodeList);
to convert your DOM collection to plain array.
I recently had cause to solve a particular problem in a similar manner and was interested to see how others had approached it. Bearing in mind the caveats posted about extending native prototypes, I'm just logging my solution, implemented in a browser environment only, for posterity.
/* For Arrays, enumerable Objects,
DOMTokenLists and HTMLCollections etc */
Object.prototype.each = function(fn) {
(Array.isArray(this) ? this : (this.constructor.name === 'Object' ? Object.keys(this) : [].slice.call(this))).forEach(fn);
};
:)
本文标签:
版权声明:本文标题:javascript - Trying to make an each method, like in jQuery, with vanilla JS - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742371031a2462240.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论