开发者

Mind boggling Function for Looping

开发者 https://www.devze.com 2023-02-18 11:27 出处:网络
If there\'s anyone who can help me understand this one, I will be impressed. It\'s #28 from John Resig\'s advanced JavaScript.

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:

  1. 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?

  2. Also, in the function, I understand that i++ goes up every time that it goes through the array.length, but what triggers num++ to increase it's value, and in what way is value == num++

  3. In function(value, i), what is value? Is value alternately 0,1,2 of the loop array? If so, how do those loop array numbers get passed as a parameter in function(value, i)

  4. 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:

  1. num is declared and initialized to 0.
  2. loop([0, 1, 2], function ...) is invoked.
  3. loop invokes fn, the anonymous function, with the array (as this), its first element, and i which indicates the element offset. (i is never actually used.)
  4. The anonymous function ASSERTs that it was passed the expected first element, 0, by comparing against num and incrementing num afterward.
  5. The anonymous function ASSERTs that its this is an Array.
  6. loop invokes fn as in #3, but with the second array element.
  7. The anonymous function again performs its ASSERTs, this time comparing the passed second array element, which is expected to be 1, against num (which, because of the post-increment in step 4, is 1).
  8. loop invokes fn as before with the third array element.
  9. The anonymous function does its ASSERTs again, this time comparing the expected array element 2 against num 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消