开发者

Javascript Evaluation Questions

var  x  =  5;
function f(y){ return (x+y)-2 }; 
function g(h){ var x = 7; return h(x) }; 
{ var x=10; z=g(f) };

I'm working through some problems from my textbook in my class to prepare for our next exam, and can't figure out how the above evaluates.

Mostly, I don't understand the call z=g(f), as when f is evaluated, it isn't provided an argument, so how does it evaluate at all? How does it know what y is?

Also, as far as scoping goes, I believe javascript treats most everything as global variables, so the last x that is set would be the x value used in function f, correct?

Thanks for any help!

Please note, these are extra problems in the back of the book I'm practicing to prepare for the exam, t开发者_如何学JAVAhese are not direct homework questions.


Mostly, I don't understand the call z=g(f), as when f is evaluated, it isn't provided an argument, so how does it evaluate at all? How does it know what y is?

Take it step by step.

Q: What does function g do?
A: It takes another function as a parameter and calls that function with the argument 7.

Q: So what does g(f) do?
A: It calls f with the argument 7, so it's equivalent to f(7).

Notice that writing f without parentheses does not actually call f. In JavaScript functions can be referred to and passed around as arguments just like any other variable. Functions are first class objects, and you can do a lot more with them than merely call them!

Q: What is the result of f(7)?
A: The return statement is return (x+7)-2. We need to know the value of x.

Q: What is the value of x inside f?
A: x here refers to the global variable x, whose value is 10. Importantly, the var x = 7 inside of g is a local variable, and is distinct from the global variable. The var x = 7 declaration from function g is irrelevant when we're looking at function f.

Also importantly, the statements var x = 5 and var x = 10 both refer to the same global variable. Local variables are only introduced inside of functions. Simply having naked curly braces and repeating the var keyword does not introduce a new variable in JavaScript. This is a tricky point, because in other languages like C++ this would introduce a new scope and a new variable. In JavaScript it does not. The var x = 10 could be (and should be!) written as simply x = 10.

To be honest, this is a remarkably subtle and confusing point. It makes me wonder if your textbook actually intended to test your knowledge of this idea. It is rather arcane.

Q: Okay... so the result of f(7) is what?
A: It is (10+7)-2, or 15.


I understand why this is confusing. Let me explain what's going on here, line by line:

var  x  =  5;

You've probably got this one figured out. A new variable x is declared and assigned the value 5.

function f(y){ return (x+y)-2 }; 

This declares a function that closes around the variable x already defined. It adds this to its argument and subtracts 2, returning that value.

function g(h){ var x = 7; return h(x) }; 

This declares a function that declares a local variable x, and then calls its argument as a function and passes it the value of x, which will always be 7.

{ var x=10; z=g(f) };

This opens a new code block and declares a variable x with a value of 10. However, since this declaration is in the same scope as the earlier declaration of x (blocks do not create new scope in JavaScript!) it will actually assign the value 10 to the existing variable. Then the block calls the function g, passing in the function f as its argument. So, what will happen? Let's start with the invocation of g:

g is passed f. Remember that g takes a function as a parameter, so this is ok. g will call f with the argument 7 and return its value. So now let's consider f. f will be called with y being equal to 7, since that was an argument. x is equal to 10, since the original x var was assigned the value 10. So it will return (x+y)-2 or (10+7)-2, which is 15.

So z will have the value 15 after the script executes.


var  x  =  5;
function f(y){ return (x+y)-2 }; 
function g(h){ var x = 7; return h(x) }; 

{ var x=10; z=g(f) };

This sets the global x to 5, then (before any function calls) 10. The braces don't create a new scope.

You pass f into the g function (it becomes formal parameter h). That is then called with x == 7 (g is a function with its own scope, so this x shadows the global).

Entering f, x becomes the formal parameter y; y is thus 7. (x + y) - 2 is then 10 + 7 - 2.


  • The global variable x is set to 5.
  • A global function f is defined, the first argument passed is aliased as y. It returns the result of global x(10) plus y, and then subtracted by two.
  • A global function g is defined, the first argument passed is alias as h. It defines x in the function body of g only. It returns the result of h executed with x passed as the first argument. h is assumed to be a function.
  • The expression { var x=10; z=g(f) }; is executed in global context and as a result, x is redefined from 5 to 10. z is assigned the result of g invoked and f is passed as an argument.

For z=g(f):

  • g is invoked. f is passed, so in the function body of g, h becomes f. x is 7 so now it calls f(7) and returns it.
  • f is invoked and returns (10+7)-2 which is 15.

The trick is that { var x = 10 } overrides 5.


Javascript supports higher-order functions, meaning functions may be passed as arguments into functions, or returned from functions. In the call z=g(f), f is not evaluated at all. The function f is passed to g, where it is evaluated (as h).

Javascript does not treat everything as global variables. Javascript uses static scoping however, meaning that the global variables used by a function are those in scope where it is defined, not where it is called.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜