1

Whenever I try to run this function in Chromium, I get the error message "Uncaught TypeError: Illegal invocation". Why does this occur, and how can I resolve it?

getOutput([alert], ["Hi!", "Hello!", "Lolwut?"]); //why doesn't this call "alert"
//for each of the arguments?

//this function is supposed to return the output of each function for each argument.
function getOutput(functions, arguments){
    for(var i = 0; i < functions.length; i++){
        for(var j = 0; j < arguments.length; j++){
            functions[i](arguments[j]); //why doesn't this call the function
        }
    }    
}​
Anderson Green
  • 25,996
  • 59
  • 164
  • 297
  • 3
    I believe [this previous SO answer handles your case](http://stackoverflow.com/a/9678166/599240). Basically it comes back to scope. – Jacques Chester Dec 18 '12 at 03:50
  • @JacquesChester It appears to be addressing a slightly different problem - I'm specifically trying to call a function from a specific index of an array. – Anderson Green Dec 18 '12 at 04:04
  • I think the *biggest* issue is that you're trying to call *a native function* from the specific index of an array. The invocation `getOutput([function(msg){alert(msg);}], ["Hi!", "Hello!", "Lolwut?"])` works. – JayC Dec 18 '12 at 04:09
  • 1
    @AndersonGreen If you look at the accepted answer, it's the same basic logic as what I linked to. I'm happy to give matehat the credit on this one, he bothered to actually write an answer :D – Jacques Chester Dec 18 '12 at 04:23

4 Answers4

3

EDIT:

Though the fix given here works, the reason seems to be as rbtLong suggested, that the native function (specifically here alert) is called outside of its context. Using a wrapper like this :

function F(arg) {alert(arg);}

in place of alert in your code as is makes the code run. Still, the suggested fix below works if you want to have a general purpose function that can take native function.


(BTW: The same occurs in Safari and Firefox)

It seems to have something to do with the array access construct not allowing invocation right after it. Maybe much like you can't do 1.toString(). You could quickly fix it like this :

getOutput([alert], ["Hi!", "Hello!", "Lolwut?"]);

function getOutput(functions, arguments){
    for(var i = 0; i < functions.length; i++){
        for(var j = 0; j < arguments.length; j++){
            var f = functions[i];
            f(arguments[j]);
        }
    }    
}​
matehat
  • 4,906
  • 2
  • 25
  • 40
  • Placing a parenthesis around it *might* work too `(functions[i])(arguments[i]);` – JCOC611 Dec 18 '12 at 03:52
  • I just tried and unfortunately it doesn't (that's what I was going to post first). `([alert][0])("hello!");` raises the same error. – matehat Dec 18 '12 at 03:53
  • Maybe `([alert][0]).call(null, arguments[j])`? (just for the sake of trying alternatives haha) – JCOC611 Dec 18 '12 at 03:56
  • It does! But I guess the property access construct pretty much had to work. Otherwise it'd be breaking quite a lot of sites :) – matehat Dec 18 '12 at 03:59
1

i believe it is because you're calling an object outside of its context the method.call(args) described here http://www.devguru.com/technologies/ecmascript/quickref/call.html should allow for it.

functions[i].call(this, arguments[j])
rbtLong
  • 1,472
  • 2
  • 13
  • 31
1

do you mean something like:

function getOutput(fn, args) { 
 for(var f = 0; f < fn.length; f++){
    for(var j = 0; j < args.length; j++){
        fun = fn[f];
        fun.call(this, args[j]);
    }
  }

}
getOutput([alert], ["Hi!", "Hello!", "Lolwut?"]);
Sudhir Bastakoti
  • 94,682
  • 14
  • 145
  • 149
0

i belive it would be like this:

fun1(fun2('lol'));

or the hard way

var hi7 = fun2('lol')

fun1(hi7)

Algo
  • 27
  • 6