-5

I have this question in an interview

Using javascript, write an array of n elements. Each element in the array is a function that calls console.log of its own index. For eg, the first element will console.log 0, second element will console.log 1....

Thanks in advance

Edit: Sorry for asking before researching. Im new to programming & dont know what closure is & couldnt find something in search. I got the answer myself but here is the problem I had. I wrote something like this

n = 10
var array = []
for (var i=0; i < n; i ++) {
array[i] = function() {
        console.log(i);
    }
}

for (var j=0; j < n; j ++) {
    array[j]()
}
hvu89
  • 69
  • 1
  • 3
  • 9
  • 1
    What's your problem? What have you tried? Do you know closures? – Bergi Jun 13 '13 at 23:17
  • 5
    _I have this question in an interview_ -- no. This is even simpler than fizzbuzz. – Halcyon Jun 13 '13 at 23:17
  • 2
    exact duplicate of [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Bergi Jun 13 '13 at 23:17

2 Answers2

2

There isn't an easy way to do what you're asking because if you put a function in each array element, that function wouldn't know what it's array index was unless you somehow bound a custom function for each array index.

But, all of this sounds a little like you're not telling us what the real problem is. If you're iterating over an array and calling a function in the array element, then just pass the index to that function as the first argument.

You could call each function in the array and pass it the index of its slot like this:

function fn1(index) {
    console.log(index);
    // do other things here specific to this function
}
// fn2 ... fn4 definitions

var listOfFunctions = [fn1, fn2, fn3, fn4];

for (var i = 0; i < listOfFunctions.length; i++) {
    listOfFunctions[i](i);
}

Or, tell us what the real problem is so we can more directly help solve that.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 5
    People get upset when you actually answer a question that is deemed to be too trivial or some kind of homework/interview question. I, on the other hand, don't believe that warrants a downvote. This is a valid answer, regardless of the morale behind the question. Someone, somewhere, may genuinely want to know the answer for more pure reasons. – mpen Jun 13 '13 at 23:22
  • @Mark - thx Mark. It looks like the downvote has been removed. The original question does leave a lot to be desired. My personal pet peeve is when people ask a question about some solution without telling us what the real problem is (this is a perfect case of that) so we can't help with the real problem. But, I try to do my best to be helpful given the info provided. – jfriend00 Jun 13 '13 at 23:25
  • (It wasn't my downvote) Still, I'm sometimes apt to downvote (any) answers on questions with [obvious duplicates](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) where better answers already exist. – Bergi Jun 13 '13 at 23:32
  • @Bergi - since the OP didn't include their own code, it's only a guess on whether this question is a dup of that or not. It could be or this could be a different issue. I didn't read it the way you did at all which is why I offered a different answer. – jfriend00 Jun 13 '13 at 23:45
  • Yeah, just passing the index is definitely the simplest way :-) It turned out the missing closure was indeed his problem. However, your current code is not working: did you forget the other 4 function declarations or did you mean `[fn1, fn1, fn1, …, fn1]`? – Bergi Jun 14 '13 at 02:38
  • @Bergi - There's no point in having the same function in every spot in an array (why bother if that's the case). I assumed the OP had N different functions in the array. I defined `fn1` just as an example, the rest of the function definitions are left to the reader. – jfriend00 Jun 14 '13 at 02:51
  • Thanks for the edit clarifying that :-) – Bergi Jun 14 '13 at 11:58
0

Here is one (of multiple ways) to do it.

var arr = [];

for (var i = 0; i < 10; i++) {
    arr.push(function(){
        console.log(this.indexOf(arguments.callee));
    });
}

arr[3](); //3
arr[7](); //7

this will refer to the array, if you call your function in the way arr[index](). arguments.callee refers to the function itself, inside of itself. So the function searches itself inside of the array that it is attached to and prints out the found index.

EDIT

As jfriend00 pointed out correnctly, arguments.callee is deprecated and is not supported in strict mode. So here is a "cleaner" solution (with suggestion from Bergi):

var arr = [], func;

for (var i = 0; i < 10; i++) {
    arr.push(function printIndex(){
        console.log(this.indexOf(printIndex));
    });
}

arr[3](); //3
arr[7](); //7
basilikum
  • 10,378
  • 5
  • 45
  • 58
  • FYI, `arguments.callee` is not supported in strict mode which is probably how we should be writing code either now or in the future. – jfriend00 Jun 13 '13 at 23:47
  • I know it's not supported. I wanted to post an answer without the use of closures (i guess because I found it nicer if the function hasn't a "hardcoded" number in it). Well...I guess I put a note at the end. Anyway, thanks for pointing it out. – basilikum Jun 13 '13 at 23:53
  • @basilikum: Just use a named function: `function findme(){ console.log(this.indexOf(findme)); }` – Bergi Jun 14 '13 at 02:39
  • @Bergi I just wanted to write that this wouldn't work since you only create one function and refer to that same function in all array items. So `indexOf` would always refer to the index 0. But I guess if you create a closure around it then it would work. Yeah, good idea. – basilikum Jun 14 '13 at 06:31
  • No, actually you don't need the closure - the function expression evaluates to a different function each time. Or at least it should, [JScript has a serious bug with named function expressions](http://kangax.github.io/nfe/#jscript-bugs). – Bergi Jun 14 '13 at 11:56
  • @Bergi A function declaration like `function printIndex(){...}` won't work for me. I'm not sure if it is standard behavior or not but at least in Chrome the function will apparently be hoisted to the very top and only evaluates once. But maybe you meant "named function expressions". I just figured out that those (`var c = function printIndex() {...}`) actually work (see updated answer). – basilikum Jun 14 '13 at 12:55
  • Yes, I meant a function expression of course - actually without any variable `func` or `c` but right in the `push()` call. – Bergi Jun 14 '13 at 13:02
  • Yes, I finally got what you meant in your first comment ;) – basilikum Jun 14 '13 at 13:04