If there's anyone who can help me understand this one, I will be impressed. It's #28 from John Resig's advanced JavaScript.
Here's a function for looping, and, if you look at the tutorial, it seems to run 3 times producing the 6 Pass below.
Can you please explain in plain language in as much detail as possible what is happening in this program, explaining along the way:
fn.call(array, array[i], i)
Why are there these 3 parameters to the function and how 开发者_运维知识库do they all work. Does the function first deal with array, then array[i], and then i? What's happening when all that is going on?Also, in the function, I understand that
i++
goes up every time that it goes through the array.length, but what triggersnum++
to increase it's value, and in what way isvalue == num++
In
function(value, i)
, what isvalue
? Is value alternately 0,1,2 of the loop array? If so, how do those loop array numbers get passed as a parameter infunction(value, i)
this instanceof Array
what is this trying to show? How?.
Code:
function loop(array, fn){
for ( var i = 0; i < array.length; i++ )
fn.call( array, array[i], i );
}
var num = 0;
loop([0, 1, 2], function(value, i){
assert(value == num++, "Make sure the contents are as we expect it.");
assert(this instanceof Array, "The context should be the full array.");
});
PASS Make sure the contents are as we expect it. PASS The context should be the full array. PASS Make sure the contents are as we expect it. PASS The context should be the full array. PASS Make sure the contents are as we expect it. PASS The context should be the full array.
The function
is an anonymous function, that is, a function without a name. The full second argument to loop
is
function(value, i) {
assert(value == num++, "Make sure the contents are as we expect it.");
assert(this instanceOf Array, "The context should be the full array.");
}
which is a complete anonymous function which takes three arguments: this
(the object for which it is a method), the current value, and the loop counter.
loop
iterates over the array, and uses fn.call
to invoke the anonymous function, passing it three arguments; here, the array object must be explicit, because call
can't know what context the function reference it's being invoked on should be invoked in (that is, what to make this
in the call).
The anonymous function, as invoked by loop
, receives the array as this
. The second ASSERT
verifies this. It also expects that the array's value is [0, 1, 2]
and verifies this by incrementing num
on each call and comparing that to the passed array element.
So, following the execution chain:
num
is declared and initialized to 0.loop([0, 1, 2], function ...)
is invoked.loop
invokesfn
, the anonymous function, with the array (asthis
), its first element, andi
which indicates the element offset. (i
is never actually used.)- The anonymous function
ASSERT
s that it was passed the expected first element, 0, by comparing againstnum
and incrementingnum
afterward. - The anonymous function
ASSERT
s that itsthis
is anArray
. loop
invokesfn
as in #3, but with the second array element.- The anonymous function again performs its
ASSERT
s, this time comparing the passed second array element, which is expected to be 1, againstnum
(which, because of the post-increment in step 4, is 1). loop
invokesfn
as before with the third array element.- The anonymous function does its
ASSERT
s again, this time comparing the expected array element 2 againstnum
whose value is now 2.
fn is a function pointer to the anonymous function that was created when invoking loop.
a) There are three parameters because the first one is a reference to the object you are going to be acting on, i.e. the array, the 2nd parameter is just current value in the iteration of the array, and the third value is location of that element in that array.
b) when you call num++, it increments the value of num. The post increment returns the value (aka assigns to value) and then increments num.
c) value is the 2nd parameter passed in by fn.call a couple lines up.
d) this refers to the array that you passed into the first parmater in your fn.call() invocation.
I think an easier way to understand what's going on is to remove the usage of call
and instead invoke the method directly - the old fashioned way.
function loop(array, fn) {
for(var i = 0; i < array.length; i++)
fn(array[i], i);
}
var num = 0;
loop([0, 1, 2], function(value, i) {
assert(value == num, "Make sure the contents are as we expect it.");
assert(this instanceof Array, "The context should be the full array.");
num++;
});
If you run this code on the source url, you would see the this instanceof Array
test fails each time, since this
is not pointing to an instance of Array anymore.
To make this
point to an instance of Array, we need to invoke the method using call
or apply
.
fn.call(array, array[i], i);
The first parameter is what this
will point to. All other parameters here are passed as arguments to the function being called. Note that we can cheat here to pass the test. Instead of passing the array
object that we are looping over, you can pass any Array object to make the second test pass.
fn.call([], array[i], i);
fn.call([1,2,3,4,5], array[i], i);
I don't actually know javascript but I believe I understand whats going on...
The first four lines are defining a function called loop. Loop takes in two variables, an array and a function. The only reason why I believe the second parameter is function is because the coder called call on the variable which probably calls the function. The function loops through the elements of the array and passes them to the function somehow through the call method. You should probably look this part up.
After the definition, num is defined to start at zero.
Then comes the fun part. The function loop is called with the parameters [0, 1, 2] and an anonymous function that was created on the spot. function(value, i) and everything after it is the definition of this anonymous function. It has no name but it just defined for this function call. The function checks to make sure that value equals num and increments num after it and then checks to makes sure the variable is an array.
精彩评论