-2

The eval() description says that, if the argument is an expression, it gets evaluated. If it's a statement, it gets executed. Well, why is it not getting executed then?

function calledf() { 
  alert("GF")
}

eval(calledf)

I would expect the function inside eval() to get executed, yet it's not. Why?

If I assign the returned value to a variable, it gives me the JS statements, without being executed.

function calledf() { 
  alert("GF")
}

var exp = eval(calledf)
alert(exp)

Why?

Note: Yes, I know that without using the brackets (), a function returns the statements inside, but the description of eval() says that, statements are being executed, and so, the returned statements should get executed. Is that not right?

definitelynotme
  • 103
  • 1
  • 6
  • 1
    "*I would expect the function inside eval() to get executed, yet it's not. Why?*" it's never *called*, why would be executed? – VLAZ Mar 12 '21 at 13:09
  • 2
    `eval` takes a *string*, not a callable. – deceze Mar 12 '21 at 13:11
  • 1
    "*the description of eval() says that, statements are being executed*" yes, it's being executed. It's ***EXACTLY*** the same as having just the function definition by itself. It declares a function. You don't see `calledf` being called without the `eval`, right? Because it's not. Declaring it a second time through `eval` doesn't *call* the function. – VLAZ Mar 12 '21 at 13:11
  • *"without using the brackets (), a function returns the statements inside"* — Wrong. Without parentheses, you're passing *the function object*. It's not "returning the statements inside". – deceze Mar 12 '21 at 13:12
  • Like @VLAZ said. You didn't call the function. `eval(calledf + "calledf();")` – invisal Mar 12 '21 at 13:12
  • 3
    Do you understand the difference between `eval(calledf)`/`eval(calledf.toString())`, `eval("calledf")` and `eval("calledf()")`? – Bergi Mar 12 '21 at 13:14
  • @Bergi No, I was hoping you guys can explain it to me. Actually, I know that `calledf()` would trigger the function and pass the returned value, but I thought `eval(calledf)` would execute the statements inside, since that is what I thought it does. I don't know the difference between just `calledf` and `"calledf"` with quotes. Also don't know `calledf.toString)` – definitelynotme Mar 12 '21 at 16:55
  • @VLAZ What do you mean by 'having a function definition by itself"? To whom does it declare the function? `calledf` being called without `eval`..? What do you mean by that? – definitelynotme Mar 12 '21 at 16:59
  • 1
    @definitelynotme Try printing them to the console and/or inspecting them in a debugger (without `eval` around it, I mean). That should make it pretty obvious. – Bergi Mar 13 '21 at 00:17

1 Answers1

3

eval takes a string, not a callable. Since you're not passing it a string, it's probably doing .toString() on the passed value:

function calledf() { 
  alert("GF")
}

console.log(calledf.toString());

Well, the string representation of a function is… its declaration form if you will. So what eval executes is this code:

function calledf() { 
  alert("GF")
}

Which does… nothing (besides declaring a function).

deceze
  • 471,072
  • 76
  • 664
  • 811
  • So, what is meant by "executing the statements" then? Am I not passing statements to the `eval` argument? If I use a variable with the name of the function in a string, and then a second variable for the parentheses, it `eval` will trigger the function. I.e. `eval("calledf" + "()")`. So, how is that different? – definitelynotme Mar 12 '21 at 17:05
  • @definitelynotme "*So, what is meant by "executing the statements" then?*" it means that you give `eval` some lines of code and it executes them. When you pass a *function reference*, it stringifies it which gives you the function *declaration*. It's effectively the same as [this code](https://jsbin.com/heyadolusa/edit?js,console) since your `eval` [does this](https://jsbin.com/wotuyocuvi/1/edit?js,console). You declare a function. But that's it - the declaration doesn't *trigger* the function. – VLAZ Mar 12 '21 at 17:16
  • I am confused about the `executing them` part. If I pass to `eval` as an argument two numerical variables, `eval` will execute the calculation, and return the sum value. `sum = eval("x * y")` if `x = 5` and `y = 2` the `eval` will pass to `sum` the value of 10. So, `eval` executes expressions, but it also says that it executes `statements`, and I though the statements inside a function will get executed, thereby actually triggering the function. That was my logic, and understanding. So, if `eval` stringifies the function, and gets the statements, why is it not executing them? – definitelynotme Mar 12 '21 at 17:50
  • @definitelynotme The difference between an expression and a statement is that an expression can be built from smaller expressions and be part of an expression. Like `x + y - z`. Every part of that is an expression, and they form a larger expression. Statements are things which can’t be part of larger expressions, like `if (...) { ... }`. You can’t do `x + if (...)`. `eval` still takes all of those **as strings** though. – deceze Mar 12 '21 at 18:43
  • @deceze Okay, I get that, but still, what is meant by `executing statements`? Does `oval` not get the function statements? Since it can pass them to a variable, it means it gets the statements. You said it `defines a function`, but why not execute the statements then? Where is the problem with this reasoning? What am I missing here? – definitelynotme Mar 12 '21 at 19:31
  • To call the function you'd need to pass code that *calls the function*: `eval('calledf()')`. – deceze Mar 12 '21 at 20:10
  • @deceze I understand that, but doesn't `eval("calledf")` get the statements from the function? If so, why does it not execute them? Isn't that what is meant by `executing statements`? – definitelynotme Mar 12 '21 at 20:32
  • @definitelynotme "*what is meant by executing statements?*" exactly what it says. The statement will be executed. "*You said it defines a function, but why not execute the statements then?*" defining a function ***is*** what the statement you give it is. A *function declaration* is a statement in JavaScript. There are also function *expressions*. See [var functionName = function() {} vs function functionName() {}](https://stackoverflow.com/q/336859). When the function declaration statement is executed, the result is that a function is declared. – VLAZ Mar 12 '21 at 20:40
  • Because `calledf` doesn't *call* the function, it just refers to the function object and does nothing with it. A function call always involves `()`. – deceze Mar 12 '21 at 20:57
  • @VLAZ I think I understand now. The execution of the statements is how the function is defined, but not triggered. So, this is what is meant by 'statement execution', where as 'expression execution' is when I have, let's say two numerical variables, and `executing` them is "calculating" them, right? `x = 5, y = 10, eval(x + y)`, now `eval` will `execute` those expressions by calculating them & returning the value, correct? What is the difference between using quotes vs not using quotes? `eval(x + y)` vs `eval("x" + "y")` vs `eval("x +y")`? Is there a difference? Same question for `calledf`. – definitelynotme Mar 12 '21 at 21:30
  • 1
    @definitelynotme `eval(x + y)` will *first* resolve the expression `x + y` (the result is `15`) and *then* call `eval("15")`. `eval` will "evaluate" the numeric literal `15` and return the result `15`; `eval("x" + "y")` will resolve `"x" + "y"` (the result is `"xy"`) and call `eval("xy")`. This would cause `eval` to try and read the variable `xy` but should produce a ReferenceError because there is no such variable; `eval("x +y")` directly passes the expression `x +y` to `eval`, so the result would be reading the two variables, and using `+` on their values. Thus you'd get `15`. – VLAZ Mar 12 '21 at 22:10
  • @VLAZ I am having trouble understanding the difference between `eval(x)` and `eval("x")`. In your example, `eval(x+y)`, you said, `eval` first resolves the expression, then evaluates the outcome, and returns it as a value. Well, how is that different from ("x + y")? You said it `directly passes the expression to eval`, what is that mean exactly? Does it not resolve the expression? Instead it passes it.. to `eval`? But is it not already inside`eval`? What does it mean to "pass" the expression, and when does it get resolved? Sorry, It's just a bit confusing. – definitelynotme Mar 12 '21 at 23:03
  • @definitelynotme "*`eval(x+y)`, you said, `eval` first resolves the expression*" **no**, the expression is resolved *before* it's given to `eval`. Whenever you have a function call `fn(arg)`, any expressions in arguments list are resolved *before* the function is called. So, if `arg` is `1 + 2` you'd call `fn(3)`. Otherwise you cannot really call the function without supplying a value. "*Well, how is that different from ("x + y")?*" that's the difference - `eval(x + y)` will only work with *the result* of `x + y` while `eval("x + y")` will evaluate the result itself. – VLAZ Mar 12 '21 at 23:07
  • @VLAZ `eval("x + y") will evaluate the result itself`.. meaning.. what? Can you elaborate on this a bit more? What do you mean by `it will evaluate the result itself`? Without the parentheses, it is resolved, and then the function triggered with the result. With parentheses.. what happens? Does it not get resolved again, and then the function triggered with the result? I think I sort of understand what you mean, but I can't translate that into `eval`. I get that, if we're talking about function instead, `function(5+5)`, it will first resolve it, &then trigger the function with 10 as argument. – definitelynotme Mar 12 '21 at 23:49
  • @VLAZ ..however `function("x")` will trigger the function with `x` being passed as a string. Is that what you're trying to tell me happens with `eval`? – definitelynotme Mar 12 '21 at 23:50
  • @definitelynotme "* I get that, if we're talking about function instead, function(5+5), it will first resolve it, &then trigger the function with 10 as argument.*" `eval` **is** a function. So, the same applies `eval(x+y)` means resolve `x+y` first, *then* call `eval`. The difference with `eval("x + y")` is *when* the result of the expression `x + y` would be resolved - before or after calling `eval`. [See here](https://jsbin.com/pegeyiniyo/1/edit?js,console) – VLAZ Mar 12 '21 at 23:58
  • @VLAZ So, when is that `after` exactly? If I understand you correctly, `("x+y")` means, the argument is not resolved before the `eval` is triggered, but AFTER eval is triggered. So, first of all, what is the argument with which `eval` is triggered with? And second, when is the argument being resolved then? – definitelynotme Mar 13 '21 at 12:39
  • @VLAZ Tell me if I am right or wrong. `Eval` evaluates the expression or statement inside the argument. The argument has to be a string. If it's not a string, it resolves it first, turns it into a string, and then evaluates it. So, `(x+y)` is not a string, so it resolves it first, then `eval` is triggered with the outcome as a string, which then gets evaluated. `("x+y")` is a string, so eval is triggered with the string, and the expressions are evaluated, meaning, calculated, and the value is returned. Is that correct, or not quite? – definitelynotme Mar 13 '21 at 12:42
  • @definitelynotme Try: `e1 = 1 + 2; e2 = '1 + 2'; console.log(e1, eval(e1), e2, eval(e2));` `1 + 2` gets evaluated before being assigned to `e1` even. `e2` on the other hand is just a string and gets passed exactly as is to `eval`. – deceze Mar 13 '21 at 17:39
  • @deceze So it gets passed, and then eval evaluates it? Is my understanding above correct, or not? – definitelynotme Mar 13 '21 at 19:28
  • @definitely `1 + 2` gets evaluated to `3` by general Javascript rules, so you would pass `3` to `eval`, which turns it into a string `'3'`, and then evaluates it as code to the value `3`. OTOH, `'1 + 2'` is a string by normal Javascript rules, which you can pass to `eval`, which then evaluates it as Javascript code. You’re supposed to pass literal Javascript code as string to `eval` which will then evaluate those string contents as Javascript code. That’s its purpose. – deceze Mar 13 '21 at 19:35
  • @deceze Okay, I think I understand this now. Do you mind me asking you another a bit unrelated question about the XMLHttprequest object, and its receiveText and receiveXML properties? – definitelynotme Mar 13 '21 at 22:14