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 asy
. 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 ash
. It definesx
in the function body ofg
only. It returns the result ofh
executed withx
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 ofg
invoked andf
is passed as an argument.
For z=g(f)
:
- g is invoked.
f
is passed, so in the function body ofg
,h
becomesf
.x
is7
so now it callsf(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.
精彩评论