declaring a variable twice in IIFEScope of Default function parameters in javascriptWhy would a JavaScript variable start with a dollar sign?How do you use a variable in a regular expression?What is the scope of variables in JavaScript?How do you check if a variable is an array in JavaScript?How do I declare a namespace in JavaScript?How to determine if variable is 'undefined' or 'null'?Check if a variable is a string in JavaScriptRead environment variables in Node.jsJavaScript check if variable exists (is defined/initialized)Is there a standard function to check for null, undefined, or blank variables in JavaScript?

Multi tool use
Banach space and Hilbert space topology
What Brexit solution does the DUP want?
Is Social Media Science Fiction?
How do I create uniquely male characters?
Why has Russell's definition of numbers using equivalence classes been finally abandoned? ( If it has actually been abandoned).
The magic money tree problem
What makes Graph invariants so useful/important?
Shell script can be run only with sh command
The use of multiple foreign keys on same column in SQL Server
Prevent a directory in /tmp from being deleted
What are these boxed doors outside store fronts in New York?
Extreme, but not acceptable situation and I can't start the work tomorrow morning
A newer friend of my brother's gave him a load of baseball cards that are supposedly extremely valuable. Is this a scam?
What is the command to reset a PC without deleting any files
Accidentally leaked the solution to an assignment, what to do now? (I'm the prof)
Simulate Bitwise Cyclic Tag
Why is the design of haulage companies so “special”?
How to calculate implied correlation via observed market price (Margrabe option)
"which" command doesn't work / path of Safari?
Why is "Reports" in sentence down without "The"
Are white and non-white police officers equally likely to kill black suspects?
Can I interfere when another PC is about to be attacked?
If Manufacturer spice model and Datasheet give different values which should I use?
I see my dog run
declaring a variable twice in IIFE
Scope of Default function parameters in javascriptWhy would a JavaScript variable start with a dollar sign?How do you use a variable in a regular expression?What is the scope of variables in JavaScript?How do you check if a variable is an array in JavaScript?How do I declare a namespace in JavaScript?How to determine if variable is 'undefined' or 'null'?Check if a variable is a string in JavaScriptRead environment variables in Node.jsJavaScript check if variable exists (is defined/initialized)Is there a standard function to check for null, undefined, or blank variables in JavaScript?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I came through this fun quiz on the internet.
console.log((function(x, f = (() => x))
var x;
var y = x;
x = 2;
return [x, y, f()]
)(1))
and the choices were:
[2,1,1]
[2, undefined, 1]
[2, 1, 2]
[2, undefined, 2]
I picked solution 2 TBH, basing that on that x has been redefined, y was declared and defined with no value, and that f has a different scope hence getting the global x memory spot than function x memory spot.
However, I tried it in jsbin.com
and I found it was solution 1, while I was not sure why that happened I messed with the function body and I removed var x
from the function body, I found that the response changed to #3 which makes sense as x value changed and hence it showed x and f as 2 and y as 1 which was declared globally.
but still I can't get why it shows 1 instead of undefined.
javascript iife
|
show 2 more comments
I came through this fun quiz on the internet.
console.log((function(x, f = (() => x))
var x;
var y = x;
x = 2;
return [x, y, f()]
)(1))
and the choices were:
[2,1,1]
[2, undefined, 1]
[2, 1, 2]
[2, undefined, 2]
I picked solution 2 TBH, basing that on that x has been redefined, y was declared and defined with no value, and that f has a different scope hence getting the global x memory spot than function x memory spot.
However, I tried it in jsbin.com
and I found it was solution 1, while I was not sure why that happened I messed with the function body and I removed var x
from the function body, I found that the response changed to #3 which makes sense as x value changed and hence it showed x and f as 2 and y as 1 which was declared globally.
but still I can't get why it shows 1 instead of undefined.
javascript iife
1
I find the best way to figure these things out is to step through them line by line with a debugger, and/or print out the values after each line.
– Heretic Monkey
13 hours ago
var x;
doesn't define a new variable within the function scope, wherevar x = somevalue;
would
– Alex
13 hours ago
2
@alex it does. ...
– Jonas Wilms
13 hours ago
@JonasWilms I see, would have expected x to be undefined then, implicitly copy the function formal value looks really odd to me.
– Alex
12 hours ago
3
I'm glad this question was asked :)
– Pointy
12 hours ago
|
show 2 more comments
I came through this fun quiz on the internet.
console.log((function(x, f = (() => x))
var x;
var y = x;
x = 2;
return [x, y, f()]
)(1))
and the choices were:
[2,1,1]
[2, undefined, 1]
[2, 1, 2]
[2, undefined, 2]
I picked solution 2 TBH, basing that on that x has been redefined, y was declared and defined with no value, and that f has a different scope hence getting the global x memory spot than function x memory spot.
However, I tried it in jsbin.com
and I found it was solution 1, while I was not sure why that happened I messed with the function body and I removed var x
from the function body, I found that the response changed to #3 which makes sense as x value changed and hence it showed x and f as 2 and y as 1 which was declared globally.
but still I can't get why it shows 1 instead of undefined.
javascript iife
I came through this fun quiz on the internet.
console.log((function(x, f = (() => x))
var x;
var y = x;
x = 2;
return [x, y, f()]
)(1))
and the choices were:
[2,1,1]
[2, undefined, 1]
[2, 1, 2]
[2, undefined, 2]
I picked solution 2 TBH, basing that on that x has been redefined, y was declared and defined with no value, and that f has a different scope hence getting the global x memory spot than function x memory spot.
However, I tried it in jsbin.com
and I found it was solution 1, while I was not sure why that happened I messed with the function body and I removed var x
from the function body, I found that the response changed to #3 which makes sense as x value changed and hence it showed x and f as 2 and y as 1 which was declared globally.
but still I can't get why it shows 1 instead of undefined.
javascript iife
javascript iife
asked 13 hours ago
Hamza MohamedHamza Mohamed
689423
689423
1
I find the best way to figure these things out is to step through them line by line with a debugger, and/or print out the values after each line.
– Heretic Monkey
13 hours ago
var x;
doesn't define a new variable within the function scope, wherevar x = somevalue;
would
– Alex
13 hours ago
2
@alex it does. ...
– Jonas Wilms
13 hours ago
@JonasWilms I see, would have expected x to be undefined then, implicitly copy the function formal value looks really odd to me.
– Alex
12 hours ago
3
I'm glad this question was asked :)
– Pointy
12 hours ago
|
show 2 more comments
1
I find the best way to figure these things out is to step through them line by line with a debugger, and/or print out the values after each line.
– Heretic Monkey
13 hours ago
var x;
doesn't define a new variable within the function scope, wherevar x = somevalue;
would
– Alex
13 hours ago
2
@alex it does. ...
– Jonas Wilms
13 hours ago
@JonasWilms I see, would have expected x to be undefined then, implicitly copy the function formal value looks really odd to me.
– Alex
12 hours ago
3
I'm glad this question was asked :)
– Pointy
12 hours ago
1
1
I find the best way to figure these things out is to step through them line by line with a debugger, and/or print out the values after each line.
– Heretic Monkey
13 hours ago
I find the best way to figure these things out is to step through them line by line with a debugger, and/or print out the values after each line.
– Heretic Monkey
13 hours ago
var x;
doesn't define a new variable within the function scope, where var x = somevalue;
would– Alex
13 hours ago
var x;
doesn't define a new variable within the function scope, where var x = somevalue;
would– Alex
13 hours ago
2
2
@alex it does. ...
– Jonas Wilms
13 hours ago
@alex it does. ...
– Jonas Wilms
13 hours ago
@JonasWilms I see, would have expected x to be undefined then, implicitly copy the function formal value looks really odd to me.
– Alex
12 hours ago
@JonasWilms I see, would have expected x to be undefined then, implicitly copy the function formal value looks really odd to me.
– Alex
12 hours ago
3
3
I'm glad this question was asked :)
– Pointy
12 hours ago
I'm glad this question was asked :)
– Pointy
12 hours ago
|
show 2 more comments
2 Answers
2
active
oldest
votes
but still I can't get why it shows 1 instead of undefined.
It's not just you. This is a deep, dark part of the specification. :-)
The key here is that there are two x
s. Yes, really. There's the parameter x
, and there's the variable x
.
A parameter list containing expressions (like f
's default value) has its own scope separate from the function body's scope. But prior to parameter lists possibly having expressions, having var x
within a function with an x
parameter had no effect (x
was still the parameter, with the parameter's value). So to preserve that, when there's a parameter list with expressions in it, a separate variable is created and the value of the parameter is copied to the variable at the beginning of the function body. Which is the reason for this seemingly-odd (no, not just seemingly) odd behavior. (If you're the kind who likes to dive into the spec, this copying is Step 28 of FunctionDeclarationInstantiation.)
Since f
's default value, () => x
, is created within the parameter list scope, it refers to the parameter x
, not the var.
So the first solution, [2, 1, 1]
is correct, because:
2
was assigned to the varx
in the function body. So at the end of the function, the varx
is2
.1
was assigned toy
from the varx
beforex
got the value2
, so at the end of the function,y
is1
.- The parameter
x
's value has never changed, sof()
results in1
at the end of the function
It's as though the code were written like this instead (I've removed unnecessary parens and added missing semicolons):
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
...I removed var x from the function body, I found that the response changed to #3...
#3 is [2, 1, 2]
. That's correct, because when you remove the var x
from the function, there's only one x
, the parameter (inherited by the function body from the parmeter list). So assigning 2
to x
changes the parameter's value, which f
returns.
Taking the earier example with param_x
and var_x
, here's what it looks like if you remove the var x;
from it:
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
Here's an annotated description of the original code (with the extraneous parentheses removed and missing semicolons added):
// /---- the parameter "x"
// v vvvvvvvvvvv--- the parameter "f" with a default value
console.log(function(x, f = () => x)
var x; // <=== the *variable* x, which gets its initial value from the
// parameter x
var y = x; // <=== sets y to 1 (x's current value)
x = 2; // <=== changes the *variable* x's value to 2
// +---------- 2, because this is the *variable* x
// (1));
Final note regarding your title:
declaring a variable twice in IIFE
The variable is only declared once. The other thing is a parameter, not a variable. The distinction is rarely important...this being one of those rare times. :-)
1
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions inclass
declarations.
– Pointy
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
Well field declarations are jarring to me becausethis
is the instance, not thethis
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think ofclass
declarations as being something akin to macro expansion.
– Pointy
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after thesuper
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.
– T.J. Crowder
12 hours ago
add a comment |
The tricky part of that code is that the =>
function is created as part of a default parameter value expression. In parameter default value expressions, the scope includes the parameters declared to the left, which in this case includes the parameter x
. Thus for that reason the x
in the =>
function is in fact the first parameter.
The function is called with just one parameter, 1
, so when the =>
function is called that's what it returns, giving [2, 1, 1]
.
The var x
declaration, as Mr Crowder points out, has the (somewhat weird, at least to me) effect of making a new x
in the function scope, into which is copied the value of the parameter x
. Without it, there's only the one (the parameter).
That still does not explain why removingvar x;
results in 2, 1, 2 ...
– Jonas Wilms
13 hours ago
@JonasWilms you're right; thevar
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if thevar
declaration creates a newx
in the function scope, but it clearly gets the value of the parameterx
anyway (which I'd expect), leaving the parameter apparently in its own scope.
– Pointy
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
It makes sense. As noted in the spec:NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.
– Jonas Wilms
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55560027%2fdeclaring-a-variable-twice-in-iife%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
but still I can't get why it shows 1 instead of undefined.
It's not just you. This is a deep, dark part of the specification. :-)
The key here is that there are two x
s. Yes, really. There's the parameter x
, and there's the variable x
.
A parameter list containing expressions (like f
's default value) has its own scope separate from the function body's scope. But prior to parameter lists possibly having expressions, having var x
within a function with an x
parameter had no effect (x
was still the parameter, with the parameter's value). So to preserve that, when there's a parameter list with expressions in it, a separate variable is created and the value of the parameter is copied to the variable at the beginning of the function body. Which is the reason for this seemingly-odd (no, not just seemingly) odd behavior. (If you're the kind who likes to dive into the spec, this copying is Step 28 of FunctionDeclarationInstantiation.)
Since f
's default value, () => x
, is created within the parameter list scope, it refers to the parameter x
, not the var.
So the first solution, [2, 1, 1]
is correct, because:
2
was assigned to the varx
in the function body. So at the end of the function, the varx
is2
.1
was assigned toy
from the varx
beforex
got the value2
, so at the end of the function,y
is1
.- The parameter
x
's value has never changed, sof()
results in1
at the end of the function
It's as though the code were written like this instead (I've removed unnecessary parens and added missing semicolons):
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
...I removed var x from the function body, I found that the response changed to #3...
#3 is [2, 1, 2]
. That's correct, because when you remove the var x
from the function, there's only one x
, the parameter (inherited by the function body from the parmeter list). So assigning 2
to x
changes the parameter's value, which f
returns.
Taking the earier example with param_x
and var_x
, here's what it looks like if you remove the var x;
from it:
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
Here's an annotated description of the original code (with the extraneous parentheses removed and missing semicolons added):
// /---- the parameter "x"
// v vvvvvvvvvvv--- the parameter "f" with a default value
console.log(function(x, f = () => x)
var x; // <=== the *variable* x, which gets its initial value from the
// parameter x
var y = x; // <=== sets y to 1 (x's current value)
x = 2; // <=== changes the *variable* x's value to 2
// +---------- 2, because this is the *variable* x
// (1));
Final note regarding your title:
declaring a variable twice in IIFE
The variable is only declared once. The other thing is a parameter, not a variable. The distinction is rarely important...this being one of those rare times. :-)
1
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions inclass
declarations.
– Pointy
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
Well field declarations are jarring to me becausethis
is the instance, not thethis
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think ofclass
declarations as being something akin to macro expansion.
– Pointy
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after thesuper
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.
– T.J. Crowder
12 hours ago
add a comment |
but still I can't get why it shows 1 instead of undefined.
It's not just you. This is a deep, dark part of the specification. :-)
The key here is that there are two x
s. Yes, really. There's the parameter x
, and there's the variable x
.
A parameter list containing expressions (like f
's default value) has its own scope separate from the function body's scope. But prior to parameter lists possibly having expressions, having var x
within a function with an x
parameter had no effect (x
was still the parameter, with the parameter's value). So to preserve that, when there's a parameter list with expressions in it, a separate variable is created and the value of the parameter is copied to the variable at the beginning of the function body. Which is the reason for this seemingly-odd (no, not just seemingly) odd behavior. (If you're the kind who likes to dive into the spec, this copying is Step 28 of FunctionDeclarationInstantiation.)
Since f
's default value, () => x
, is created within the parameter list scope, it refers to the parameter x
, not the var.
So the first solution, [2, 1, 1]
is correct, because:
2
was assigned to the varx
in the function body. So at the end of the function, the varx
is2
.1
was assigned toy
from the varx
beforex
got the value2
, so at the end of the function,y
is1
.- The parameter
x
's value has never changed, sof()
results in1
at the end of the function
It's as though the code were written like this instead (I've removed unnecessary parens and added missing semicolons):
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
...I removed var x from the function body, I found that the response changed to #3...
#3 is [2, 1, 2]
. That's correct, because when you remove the var x
from the function, there's only one x
, the parameter (inherited by the function body from the parmeter list). So assigning 2
to x
changes the parameter's value, which f
returns.
Taking the earier example with param_x
and var_x
, here's what it looks like if you remove the var x;
from it:
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
Here's an annotated description of the original code (with the extraneous parentheses removed and missing semicolons added):
// /---- the parameter "x"
// v vvvvvvvvvvv--- the parameter "f" with a default value
console.log(function(x, f = () => x)
var x; // <=== the *variable* x, which gets its initial value from the
// parameter x
var y = x; // <=== sets y to 1 (x's current value)
x = 2; // <=== changes the *variable* x's value to 2
// +---------- 2, because this is the *variable* x
// (1));
Final note regarding your title:
declaring a variable twice in IIFE
The variable is only declared once. The other thing is a parameter, not a variable. The distinction is rarely important...this being one of those rare times. :-)
1
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions inclass
declarations.
– Pointy
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
Well field declarations are jarring to me becausethis
is the instance, not thethis
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think ofclass
declarations as being something akin to macro expansion.
– Pointy
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after thesuper
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.
– T.J. Crowder
12 hours ago
add a comment |
but still I can't get why it shows 1 instead of undefined.
It's not just you. This is a deep, dark part of the specification. :-)
The key here is that there are two x
s. Yes, really. There's the parameter x
, and there's the variable x
.
A parameter list containing expressions (like f
's default value) has its own scope separate from the function body's scope. But prior to parameter lists possibly having expressions, having var x
within a function with an x
parameter had no effect (x
was still the parameter, with the parameter's value). So to preserve that, when there's a parameter list with expressions in it, a separate variable is created and the value of the parameter is copied to the variable at the beginning of the function body. Which is the reason for this seemingly-odd (no, not just seemingly) odd behavior. (If you're the kind who likes to dive into the spec, this copying is Step 28 of FunctionDeclarationInstantiation.)
Since f
's default value, () => x
, is created within the parameter list scope, it refers to the parameter x
, not the var.
So the first solution, [2, 1, 1]
is correct, because:
2
was assigned to the varx
in the function body. So at the end of the function, the varx
is2
.1
was assigned toy
from the varx
beforex
got the value2
, so at the end of the function,y
is1
.- The parameter
x
's value has never changed, sof()
results in1
at the end of the function
It's as though the code were written like this instead (I've removed unnecessary parens and added missing semicolons):
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
...I removed var x from the function body, I found that the response changed to #3...
#3 is [2, 1, 2]
. That's correct, because when you remove the var x
from the function, there's only one x
, the parameter (inherited by the function body from the parmeter list). So assigning 2
to x
changes the parameter's value, which f
returns.
Taking the earier example with param_x
and var_x
, here's what it looks like if you remove the var x;
from it:
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
Here's an annotated description of the original code (with the extraneous parentheses removed and missing semicolons added):
// /---- the parameter "x"
// v vvvvvvvvvvv--- the parameter "f" with a default value
console.log(function(x, f = () => x)
var x; // <=== the *variable* x, which gets its initial value from the
// parameter x
var y = x; // <=== sets y to 1 (x's current value)
x = 2; // <=== changes the *variable* x's value to 2
// +---------- 2, because this is the *variable* x
// (1));
Final note regarding your title:
declaring a variable twice in IIFE
The variable is only declared once. The other thing is a parameter, not a variable. The distinction is rarely important...this being one of those rare times. :-)
but still I can't get why it shows 1 instead of undefined.
It's not just you. This is a deep, dark part of the specification. :-)
The key here is that there are two x
s. Yes, really. There's the parameter x
, and there's the variable x
.
A parameter list containing expressions (like f
's default value) has its own scope separate from the function body's scope. But prior to parameter lists possibly having expressions, having var x
within a function with an x
parameter had no effect (x
was still the parameter, with the parameter's value). So to preserve that, when there's a parameter list with expressions in it, a separate variable is created and the value of the parameter is copied to the variable at the beginning of the function body. Which is the reason for this seemingly-odd (no, not just seemingly) odd behavior. (If you're the kind who likes to dive into the spec, this copying is Step 28 of FunctionDeclarationInstantiation.)
Since f
's default value, () => x
, is created within the parameter list scope, it refers to the parameter x
, not the var.
So the first solution, [2, 1, 1]
is correct, because:
2
was assigned to the varx
in the function body. So at the end of the function, the varx
is2
.1
was assigned toy
from the varx
beforex
got the value2
, so at the end of the function,y
is1
.- The parameter
x
's value has never changed, sof()
results in1
at the end of the function
It's as though the code were written like this instead (I've removed unnecessary parens and added missing semicolons):
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
...I removed var x from the function body, I found that the response changed to #3...
#3 is [2, 1, 2]
. That's correct, because when you remove the var x
from the function, there's only one x
, the parameter (inherited by the function body from the parmeter list). So assigning 2
to x
changes the parameter's value, which f
returns.
Taking the earier example with param_x
and var_x
, here's what it looks like if you remove the var x;
from it:
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
Here's an annotated description of the original code (with the extraneous parentheses removed and missing semicolons added):
// /---- the parameter "x"
// v vvvvvvvvvvv--- the parameter "f" with a default value
console.log(function(x, f = () => x)
var x; // <=== the *variable* x, which gets its initial value from the
// parameter x
var y = x; // <=== sets y to 1 (x's current value)
x = 2; // <=== changes the *variable* x's value to 2
// +---------- 2, because this is the *variable* x
// (1));
Final note regarding your title:
declaring a variable twice in IIFE
The variable is only declared once. The other thing is a parameter, not a variable. The distinction is rarely important...this being one of those rare times. :-)
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
console.log(function(param_x, f = () => param_x)
var var_x = param_x;
var y = var_x;
var_x = 2;
return [var_x, y, f()];
(1));
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
console.log(function(param_x, f = () => param_x)
var y = param_x;
param_x = 2;
return [param_x, y, f()];
(1));
edited 12 hours ago
answered 13 hours ago
T.J. CrowderT.J. Crowder
699k12312431341
699k12312431341
1
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions inclass
declarations.
– Pointy
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
Well field declarations are jarring to me becausethis
is the instance, not thethis
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think ofclass
declarations as being something akin to macro expansion.
– Pointy
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after thesuper
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.
– T.J. Crowder
12 hours ago
add a comment |
1
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions inclass
declarations.
– Pointy
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
Well field declarations are jarring to me becausethis
is the instance, not thethis
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think ofclass
declarations as being something akin to macro expansion.
– Pointy
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after thesuper
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.
– T.J. Crowder
12 hours ago
1
1
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions in
class
declarations.– Pointy
12 hours ago
This is now in my list of "new weird things about JavaScript" alongside the semantics of (not yet really standard) instance property initialization expressions in
class
declarations.– Pointy
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
@Pointy - Oh, this is much weirder than field declarations. :-D
– T.J. Crowder
12 hours ago
Well field declarations are jarring to me because
this
is the instance, not the this
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think of class
declarations as being something akin to macro expansion.– Pointy
12 hours ago
Well field declarations are jarring to me because
this
is the instance, not the this
of the surrounding scope as with object initializers. I guess it's not really "weird" if you think of class
declarations as being something akin to macro expansion.– Pointy
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after the
super
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.– T.J. Crowder
12 hours ago
@Pointy - Yeah. I think of them as code that's relocated to the beginning of the constructor (just after the
super
call if it's a subclass). That's what Java does with instance field initializers and instance initialization blocks (and they're literally copied to the beginning of each constructor in Java; thankfully in JavaScript we just have the one). JavaScript took effectively the same approach.– T.J. Crowder
12 hours ago
add a comment |
The tricky part of that code is that the =>
function is created as part of a default parameter value expression. In parameter default value expressions, the scope includes the parameters declared to the left, which in this case includes the parameter x
. Thus for that reason the x
in the =>
function is in fact the first parameter.
The function is called with just one parameter, 1
, so when the =>
function is called that's what it returns, giving [2, 1, 1]
.
The var x
declaration, as Mr Crowder points out, has the (somewhat weird, at least to me) effect of making a new x
in the function scope, into which is copied the value of the parameter x
. Without it, there's only the one (the parameter).
That still does not explain why removingvar x;
results in 2, 1, 2 ...
– Jonas Wilms
13 hours ago
@JonasWilms you're right; thevar
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if thevar
declaration creates a newx
in the function scope, but it clearly gets the value of the parameterx
anyway (which I'd expect), leaving the parameter apparently in its own scope.
– Pointy
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
It makes sense. As noted in the spec:NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.
– Jonas Wilms
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
add a comment |
The tricky part of that code is that the =>
function is created as part of a default parameter value expression. In parameter default value expressions, the scope includes the parameters declared to the left, which in this case includes the parameter x
. Thus for that reason the x
in the =>
function is in fact the first parameter.
The function is called with just one parameter, 1
, so when the =>
function is called that's what it returns, giving [2, 1, 1]
.
The var x
declaration, as Mr Crowder points out, has the (somewhat weird, at least to me) effect of making a new x
in the function scope, into which is copied the value of the parameter x
. Without it, there's only the one (the parameter).
That still does not explain why removingvar x;
results in 2, 1, 2 ...
– Jonas Wilms
13 hours ago
@JonasWilms you're right; thevar
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if thevar
declaration creates a newx
in the function scope, but it clearly gets the value of the parameterx
anyway (which I'd expect), leaving the parameter apparently in its own scope.
– Pointy
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
It makes sense. As noted in the spec:NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.
– Jonas Wilms
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
add a comment |
The tricky part of that code is that the =>
function is created as part of a default parameter value expression. In parameter default value expressions, the scope includes the parameters declared to the left, which in this case includes the parameter x
. Thus for that reason the x
in the =>
function is in fact the first parameter.
The function is called with just one parameter, 1
, so when the =>
function is called that's what it returns, giving [2, 1, 1]
.
The var x
declaration, as Mr Crowder points out, has the (somewhat weird, at least to me) effect of making a new x
in the function scope, into which is copied the value of the parameter x
. Without it, there's only the one (the parameter).
The tricky part of that code is that the =>
function is created as part of a default parameter value expression. In parameter default value expressions, the scope includes the parameters declared to the left, which in this case includes the parameter x
. Thus for that reason the x
in the =>
function is in fact the first parameter.
The function is called with just one parameter, 1
, so when the =>
function is called that's what it returns, giving [2, 1, 1]
.
The var x
declaration, as Mr Crowder points out, has the (somewhat weird, at least to me) effect of making a new x
in the function scope, into which is copied the value of the parameter x
. Without it, there's only the one (the parameter).
edited 13 hours ago
answered 13 hours ago
PointyPointy
321k45461528
321k45461528
That still does not explain why removingvar x;
results in 2, 1, 2 ...
– Jonas Wilms
13 hours ago
@JonasWilms you're right; thevar
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if thevar
declaration creates a newx
in the function scope, but it clearly gets the value of the parameterx
anyway (which I'd expect), leaving the parameter apparently in its own scope.
– Pointy
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
It makes sense. As noted in the spec:NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.
– Jonas Wilms
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
add a comment |
That still does not explain why removingvar x;
results in 2, 1, 2 ...
– Jonas Wilms
13 hours ago
@JonasWilms you're right; thevar
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if thevar
declaration creates a newx
in the function scope, but it clearly gets the value of the parameterx
anyway (which I'd expect), leaving the parameter apparently in its own scope.
– Pointy
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
It makes sense. As noted in the spec:NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.
– Jonas Wilms
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
That still does not explain why removing
var x;
results in 2, 1, 2 ...– Jonas Wilms
13 hours ago
That still does not explain why removing
var x;
results in 2, 1, 2 ...– Jonas Wilms
13 hours ago
@JonasWilms you're right; the
var
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if the var
declaration creates a new x
in the function scope, but it clearly gets the value of the parameter x
anyway (which I'd expect), leaving the parameter apparently in its own scope.– Pointy
13 hours ago
@JonasWilms you're right; the
var
declaration must ... do something but it doesn't seem obvious to me what that is. It's as if the var
declaration creates a new x
in the function scope, but it clearly gets the value of the parameter x
anyway (which I'd expect), leaving the parameter apparently in its own scope.– Pointy
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
I guess the values are somewhat copied from the default initializers scope to the bodies scope. Im already digging into the spec
– Jonas Wilms
13 hours ago
It makes sense. As noted in the spec:
NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.– Jonas Wilms
12 hours ago
It makes sense. As noted in the spec:
NOTE: A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
thats reasonable.– Jonas Wilms
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
@Pointy - It's a very deep, dark part of the spec. :-)
– T.J. Crowder
12 hours ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55560027%2fdeclaring-a-variable-twice-in-iife%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
6uPY6Facgjwm Xd4eX9vN
1
I find the best way to figure these things out is to step through them line by line with a debugger, and/or print out the values after each line.
– Heretic Monkey
13 hours ago
var x;
doesn't define a new variable within the function scope, wherevar x = somevalue;
would– Alex
13 hours ago
2
@alex it does. ...
– Jonas Wilms
13 hours ago
@JonasWilms I see, would have expected x to be undefined then, implicitly copy the function formal value looks really odd to me.
– Alex
12 hours ago
3
I'm glad this question was asked :)
– Pointy
12 hours ago