2013-02-08 55 views
1

我經常想用forEach或map遍歷NodeList。我的簡化代碼是這樣的:如何迭代nodeList功能樣式

var nodeListMap = Array.prototype.map; 
var els = document.querySelectorAll('.classname'); 
nodeListMap.call(els, function(el){...}); 

這工作正常。但是,我寧願沒有map.call,但如果我這樣做...

var nodeListMap = Array.prototype.map.call; 
var els = document.querySelectorAll('.classname'); 
nodeListMap(els, function(el){...}); 

然後返回

TypeError: object is not a function 

我如何修改代碼,所以我根本就nodeListMap(array, fn)

回答

2

這可能是最簡單的只是寫自己的函數,「做正確的事」

function map() { 
    var args = [].slice.call(arguments, 0); 
    var ctx = args.shift(); 
    return [].map.apply(ctx, args); 
} 

那麼這將爲任何僞數組對象工作。

編輯此代碼更新,以確保所有參數傳遞給.map,即使ECMA在未來增加更多。

+0

你可能想'Array'而不是'[]' – Shmiddty 2013-02-08 19:46:06

+1

我確實有'[] .prototype.map'這當然是錯誤的,應該是'Array.prototype.map',但'[] .map'對自己的作品也是如此。 – Alnitak 2013-02-08 19:46:30

+0

@Bergi我正在修復,因爲你鍵入。 Shmiddty的答案有(有)同樣的問題。 – Alnitak 2013-02-08 19:51:44

2

Array.prototype.map.call只是讓你call功能(Function.prototype.call),沒有上下文。您需要將其綁定到map功能:

var nodeListMap = Function.prototype.call.bind(Array.prototype.map); 

如果你不想使用bind,你也可以寫

function nodeListMap(_list /* … */) { 
    return Function.prototype.call.apply(Array.prototype.map, arguments); 
} 
+0

這樣做必須有副作用。 – Shmiddty 2013-02-08 19:27:57

+0

@Shmiddty:「副作用」是什麼意思?當然,JS不是一種純粹的功能語言,並允許副作用。 – Bergi 2013-02-08 19:30:11

+0

@bergi他似乎暗示它會打破東西 – Alnitak 2013-02-08 19:41:18

2

另一種辦法是添加此功能的原型節點列表:

NodeList.prototype.map = function(step){ 
    return Array.prototype.map.call(this, step); 
}; 
NodeList.prototype.forEach = function(step){ 
    return Array.prototype.forEach.call(this, step); 
}; 

有了這個,你可能只需要調用:

els.map(function(el){...}); 

應該指出的是,有些人可能會因爲這種方式修改NodeList的原型而皺眉,但我個人並沒有真正看到它的問題。

或者,如果您需要設置this對象:

NodeList.prototype.map = function(step){ 
    return Array.prototype.map.call(this, step, Array.prototype.slice.call(arguments, 1)); 
}; 
NodeList.prototype.forEach = function(step){ 
    return Array.prototype.forEach.call(this, step, Array.prototype.slice.call(arguments, 1)); 
}; 

注:上面有一個副作用,就是當你不通過第二個參數,this成爲空的數組,而不是window

NodeList.prototype.map = Array.prototype.map; 
NodeList.prototype.forEach = Array.prototype.forEach; 
+0

這會阻止我們使用這些函數的第二個參數。爲什麼不只是'NodeList.prototype.map = Array.prototype.map;'? – Bergi 2013-02-08 19:46:32

+0

@Bergi ISTR一些瀏覽器(較老的IE?)不允許你修改內建類型的原型。不是說舊的IE實際上_has_'map()' – Alnitak 2013-02-08 19:47:17

+0

@Bergi好點。 – Shmiddty 2013-02-08 19:47:36