[] .forEach.call ()은 JavaScript에서 무엇을합니까?
몇 가지 코드 조각을보고 있었고 빈 배열에 forEach가 적용된 노드 목록에서 함수를 호출하는 여러 요소를 발견했습니다.
예를 들어 다음과 같은 것이 있습니다.
[].forEach.call( document.querySelectorAll('a'), function(el) {
// whatever with the current node
});
그러나 그것이 어떻게 작동하는지 이해할 수 없습니다. 누구든지 forEach 앞에서 빈 배열의 동작과 작동 방식을 설명 할 수 있습니까 call
?
[]
배열입니다.
이 배열은 전혀 사용되지 않습니다.
배열을 사용하면과 같은 배열 프로토 타입에 액세스 할 수 있으므로 페이지에 표시 .forEach
됩니다.
입력하는 것보다 빠릅니다. Array.prototype.forEach.call(...);
다음으로, forEach
기능을 입력으로받는 기능입니다.
[1,2,3].forEach(function (num) { console.log(num); });
...의 각 요소에 대해 this
( this
어레이와 같고 a length
와 같은 부분에 액세스 할 수 있다는 점 에서 ) 배열 this[1]
은 세 가지를 전달합니다.
- 배열 내의 요소
- 요소의 인덱스 (세번째 요소는 통과합니다
2
) - 배열에 대한 참조
마지막으로, .call
함수가 가지고있는 프로토 타입입니다 (다른 함수에서 호출되는 함수입니다).
.call
첫 번째 인자를 가지고 대체합니다 this
당신이 통과 무엇 이건 정규 함수의 내부에 call
첫 번째 인수로, ( undefined
또는 null
사용 window
일상 JS에서, 또는 당신이 경우 "엄격 모드"에서 통과 무엇이든 될 것입니다). 나머지 인수는 원래 함수로 전달됩니다.
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
따라서 forEach
함수 를 호출하는 빠른 방법을 만들고 this
빈 배열에서 모든 <a>
태그 목록으로 변경 하고 각 <a>
순서에 따라 제공된 함수를 호출합니다.
편집하다
논리적 결론 / 정리
아래에는 함수형 프로그래밍 시도를 폐기하고 매번 수동 인라인 루핑을 고수하는 기사에 대한 링크가 있습니다.
내가 그 동안 말하고 싶지만 .forEach
그 대응보다 도움이된다, .map(transformer)
, .filter(predicate)
, .reduce(combiner, initialValue)
중 하나에 접근하면서 당신이 정말로 원하는 모두가 외부 세계 (안 배열), N-시간을 수정할 때, 그것은 여전히 용도로 사용 arr[i]
또는 i
.
Motto는 분명히 재능 있고 지식이 풍부한 사람이므로 불일치를 처리하는 방법은 무엇이며, 내가하고있는 일 / 내가 가고있는 곳을 알고 있다고 상상하고 싶습니다 ... 번은 머리 우선 학습)?
대답은 실제로 매우 간단하며 밥 삼촌과 크록 포드 경은 감시로 인해 둘 다 직면 할 것입니다.
그것을 청소하십시오 .
function toArray (arrLike) { // or asArray(), or array(), or *whatever*
return [].slice.call(arrLike);
}
var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);
자, 당신이 이것을 해야하는지 여부에 대해 의문을 가지고 있다면, 대답은 아마 아닐
것입니다 ... 이 정확한 일은 요즘 고급 기능을 가진 모든 라이브러리 (?)에 의해 수행됩니다.
lodash, 밑줄 또는 jQuery를 사용하는 경우 모두 요소 집합을 취하고 n 번 동작을 수행하는 방법이 있습니다.
그런 것을 사용하지 않는다면, 반드시 자신의 것을 쓰십시오.
lib.array = (arrLike, start, end) => [].slice.call(arrLike, start, end);
lib.extend = function (subject) {
var others = lib.array(arguments, 1);
return others.reduce(appendKeys, subject);
};
Update for ES6(ES2015) and Beyond
Not only is a slice( )
/array( )
/etc helper method going to make life easier for people who want to use lists just like they use arrays (as they should), but for the people who have the luxury of operating in ES6+ browsers of the relatively-near future, or of "transpiling" in Babel today, you have language features built in, which make this type of thing unnecessary.
function countArgs (...allArgs) {
return allArgs.length;
}
function logArgs (...allArgs) {
return allArgs.forEach(arg => console.log(arg));
}
function extend (subject, ...others) { /* return ... */ }
var nodeArray = [ ...nodeList1, ...nodeList2 ];
Super-clean, and very useful.
Look up the Rest and Spread operators; try them out at the BabelJS site; if your tech stack is in order, use them in production with Babel and a build step.
There's no good reason not to be able to use the transform from non-array into array... ...just don't make a mess of your code doing nothing but pasting that same ugly line, everywhere.
The querySelectorAll
method returns a NodeList
, which is similar to an array, but it's not quite an array. Therefore, it doesn't have a forEach
method (which array objects inherit via Array.prototype
).
Since a NodeList
is similar to an array, array methods will actually work on it, so by using [].forEach.call
you are invoking the Array.prototype.forEach
method in the context of the NodeList
, as if you had been able to simply do yourNodeList.forEach(/*...*/)
.
Note that the empty array literal is just a shortcut to the expanded version, which you will probably see quite often too:
Array.prototype.forEach.call(/*...*/);
The other answers have explained this code very well, so I'll just add a suggestion.
This is a good example of code that should be refactored for simplicity and clarity. Instead of using [].forEach.call()
or Array.prototype.forEach.call()
every time you do this, make a simple function out of it:
function forEach( list, callback ) {
Array.prototype.forEach.call( list, callback );
}
Now you can call this function instead of the more complicated and obscure code:
forEach( document.querySelectorAll('a'), function( el ) {
// whatever with the current node
});
It can be better written using
Array.prototype.forEach.call( document.querySelectorAll('a'), function(el) {
});
What is does is document.querySelectorAll('a')
returns an object similar to an array, but it does not inherit from the Array
type. So we calls the forEach
method from the Array.prototype
object with the context as the value returned by document.querySelectorAll('a')
An empty array has a property forEach
in its prototype which is a Function object. (The empty array is just an easy way to obtain a reference to the forEach
function that all Array
objects have.) Function objects, in turn, have a call
property which is also a function. When you invoke a Function's call
function, it runs the function with the given arguments. The first argument becomes this
in the called function.
You can find documentation for the call
function here. Documentation for forEach
is here.
Just add one line:
NodeList.prototype.forEach = HTMLCollection.prototype.forEach = Array.prototype.forEach;
And voila!
document.querySelectorAll('a').forEach(function(el) {
// whatever with the current node
});
Enjoy :—)
Warning: NodeList is a global class. Don't use this recomendation if you writing public library. However it's very convenient way for increasing self-efficacy when you work on website or node.js app.
Just a quick and dirty solution I always end up using. I wouldn't touch prototypes, just as good practice. Of course, there are a lot of ways to make this better, but you get the idea.
const forEach = (array, callback) => {
if (!array || !array.length || !callback) return
for (var i = 0; i < array.length; i++) {
callback(array[i], i);
}
}
forEach(document.querySelectorAll('.a-class'), (item, index) => {
console.log(`Item: ${item}, index: ${index}`);
});
Want to update on this old question:
The reason to use [].foreach.call()
to loop through elements in the modern browsers is mostly over. We can use document.querySelectorAll("a").foreach()
directly.
NodeList objects are collections of nodes, usually returned by properties such as Node.childNodes and methods such as document.querySelectorAll().
Although NodeList is not an Array, it is possible to iterate over it with forEach(). It can also be converted to a real Array using Array.from().
However, some older browsers have not implemented NodeList.forEach() nor Array.from(). This can be circumvented by using Array.prototype.forEach() — see this document's Example.
[]
always returns a new array, it is equivalent to new Array()
but is guaranteed to return an array because Array
could be overwritten by the user whereas []
can not. So this is a safe way to get the prototype of Array
, then as described, call
is used to execute the function on the arraylike nodelist (this).
Calls a function with a given this value and arguments provided individually. mdn
Norguard explained WHAT [].forEach.call()
does and James Allardice WHY we do it: because querySelectorAll returns a NodeList
that doesn't have a forEach method...
Unless you have modern browser like Chrome 51+, Firefox 50+, Opera 38, Safari 10.
If not you can add a Polyfill:
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = function (callback, thisArg) {
thisArg = thisArg || window;
for (var i = 0; i < this.length; i++) {
callback.call(thisArg, this[i], i, this);
}
};
}
참고URL : https://stackoverflow.com/questions/16053357/what-does-foreach-call-do-in-javascript
'IT박스' 카테고리의 다른 글
C #에서 가비지 콜렉션 강제 실행을위한 우수 사례 (0) | 2020.07.21 |
---|---|
Xcode 찾기 발신자 기능 (0) | 2020.07.21 |
결합 된 ggplot에 공통 범례 추가 (0) | 2020.07.21 |
Docker-호스트 USB 또는 직렬 장치에 액세스하는 방법은 무엇입니까? (0) | 2020.07.21 |
필드에 $ x가 포함되지 않은 SQL 쿼리 (0) | 2020.07.21 |