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';
});
我试图在jQuery中创建每个方法。我在for循环和回调中尝试了很多东西,但是我遇到了错误。我确定这与这个&#39;这个&#39;上下文。
答案 0 :(得分:8)
您可以使用call来设置上下文
编辑:Element
不是正确的类,应该是NodeList
和HTMLCollection
NodeList.prototype.each = HTMLCollection.prototype.each = function(fn) {
for(var i = 0; i < this.length; i++) {
fn.call(this, i);
}
};
当您使用Function.prototype.call
时,它允许您将上下文AKA this
绑定到函数
AFAIK有三种方法可以做到这一点:
另请注意,自DOM level 4 (ES6 harmony)起,有一个名为Elements
的新类,其扩展为Array
,旨在取代NodeList
/ HTMLCollection
,因此您不需要在ES6中实际扩展它以添加each
方法并使用Array.prototype.forEach
代替(尽管您在回调中无法使用this
。
答案 1 :(得分:3)
document.getElementsByTagName('li')
返回HTML Collection
个对象,而不是Element
。
复制jQuery each
非常容易(原生forEach
和$.each
之间的唯一区别是参数顺序 - $.each
使用(i,el)
} tuple,[].forEach
使用(el,i)
元组。在现代浏览器中(除了IE8之外)你可以使用:
document.getElementsByTagName('li').constructor.prototype.each = function(fn,thisArg) {
[].forEach.call(this, function(el,i,array) {
fn.call(thisArg, i,el,array);
});
};
我不建议扩展原生原型,您应该使用[].forEach.call(yourNodeList, func)
代替。可以yourNodeList = [].slice.call(yourNodeList);
将DOM集合转换为普通数组。
答案 2 :(得分:0)
我最近有理由以类似的方式解决某个特定问题,并有兴趣了解其他人是如何接近它的。考虑到有关扩展原生原型的警告,我只是记录我的解决方案,仅在浏览器环境中实现,以供后人使用。
/* 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);
};
:)