可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I can't understand why variables act so strange when declared inside a function.
In the first
function I declare with let
the variables b
and c
with the value 10:
b = c = 10;
In the second
function I show:
b + ", " + c
And this shows:
10, 10
Also in first
function I declare a
with value 10:
let a = b = c = 10;
But in the second
function it shows an error:
Can't find variable: a
Now in the first
function I declare d
with value 20:
var d = 20;
But in the second
function it shows the same error as before, but with the variable d
:
Can't find variable: d
Example:
function first() {
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
try{ console.log(a); } // Rreference error
catch(e){ console.error(e.message) }
try{ console.log(d); } // Reference error
catch(e){ console.error(e.message) }
}
first()
回答1:
It's because you're actually saying:
c = 10;
b = c;
let a = b;
And not what you think you are saying, which is:
let a = 10;
let b = 10;
let c = 10;
You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.
This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.
If you declare a variable without "let", it scopes the variable globally.
So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a breakpoint). If you put a console log for a,b,c in that first function, all is well.
But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a breakpoint in the second function), but the other two (or however many you add) are still available.
This is because, "let" ONLY APPLIES TO (so only locally scopes) THE FIRST VARIABLE--again, which is technically the last to be declared and assigned a value--in the chain. The rest technically do not have "let" in front of them. So those are technically declared globally (that is, on the global object), which is why they appear in your second function.
Try it: remove the "let" keyword. All your vars will now be available.
"var" has a similar local-scope effect, but differs in how the variable is "hoisted", which is something you should definitely understand, but which is not directly involved with your question.
(BTW, this question would stump enough pro JS devs to make it a good one).
Strongly suggest you spend time with the differences in how variables can be declared in JS: without a keyword, with "let", and with "var".
回答2:
In the function first()
, variables b
and c
are created on the fly, without using var
or let
.
let a = b = c = 10; // b and c are created on the fly
Is different than
let a = 10, b = 10, c = 10; // b and c are created using let (note the ,)
They become implicit global. That's why they are available in second()
From documentation
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.
To avoid this, you can use "use strict"
that will provide errors when one use an undeclared variable
"use strict"; // <-------------- check this
function first() {
/*
* With "use strict" c is not defined.
* (Neither is b, but since the line will be executed from right to left,
* the variable c will cause the error and the script will stop)
* Without, b and c become globals, and then are accessible in other functions
*/
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //reference error
console.log(a); //reference error
console.log(d); //reference error
}
first();
回答3:
Before calling things strange, let’s know some basics first:
var and let are both used for variable declaration in JavaScript. For example,
var one = 1;
let two = 2;
Variables can also be declared without using var
or let
. For example,
three = 3;
Now the difference between the above approaches is that:
var
is function scoped
and
let
is block scoped.
while the scope of the variables declared without var
/let
keyword
become global irrespective of where it is declared.
Global variables can be accessed from anywhere in the web page (not recommended because globals can be accidentally modified).
Now according to these concepts let's have a look at the code in question:
function first() {
let a = b = c = 10;
/* The above line means:
let a=10; // Block scope
b=10; // Global scope
c=10; // Global scope
*/
var d = 20; // Function scope
second();
}
function second() {
alert(b + ", " + c); // Shows "10, 10" //accessible because of global scope
alert(a); // Error not accessible because block scope has ended
alert(d); // Error not accessible because function scope has ended
}
回答4:
Variables using the let
keyword should only be available within the scope of the block and not available in an outside function...
Each variable that you are declaring in that manner is not using let
or var
. You are missing a comma in the variables declaration.
It is not recommended to declare a variable without the var
keyword. It can accidentally overwrite an existing global variable. The scope of the variables declared without the var
keyword become global irrespective of where it is declared. Global variables can be accessed from anywhere in the web page.
function first() {
let a = 10;
let b = 10;
let c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
console.log(a); //reference error
console.log(d); //reference error
}
first();
回答5:
It's because of when you don't use let
or var
then variable is getting declare on the fly, better you declare like following.
let a = 10;
let b = 10;
let c = 10;
回答6:
The strange issue is caused by scoping rules in JavaScript
function first() {
let a = b = c = 10; // a is in local scope, b and c are in global scope
var d = 20; // d is in local scope
second(); // will have access to b and c from the global scope
}
Assuming that you want to declare 3 local variables initialised to the same value (100). Your first() will look like below. In this case, second() will not have access to any of the variables because they are local to first()
function first() {
let a = 100; // a is in local scope init to 100
let b = a; // b is in local scope init to a
let c = b // c is in local scope init to b
var d = 20; // d is in local scope
second(); // will not have access a, b, c, or d
}
However, if you want global variables then your first() will look like below. In this case, second will have access to all the variables because they are in global scope
function first() {
a = 100; // a is in global scope
b = a; // b is in global scope
c = b // c is in global scope
d = 20; // d is in global scope
second(); // will have access to a, b, c, and d from the global scope
}
Local variables (aka. accessible in the code block where they are declared).
A Code block is any {} with line(s) of code between.
- function() {var, let, const in here is accessible to entire function},
- for() {var in here is accessible to outer scope, let, const accessible only in here},
- etc.
Global variables (aka accessible in the global scope).
These variables are attached to the global object. The global object is environment dependent. It is the window object in browsers.
Special note: You can declare variables in JavaScript without using the var, let, const keywords. A variable declared this way is attached to the global object, therefore accessible in the global scope.
a = 100 // is valid and is in global scope
Some articles for further reading:
https://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/
https://scotch.io/tutorials/understanding-scope-in-javascript
https://www.digitalocean.com/community/tutorials/understanding-variables-scope-hoisting-in-javascript
回答7:
Main difference is scoping rules. Variables declared by var keyword are scoped to the immediate function body (hence the function scope) while let variables are scoped to the immediate enclosing block denoted by { } (hence the block scope). And when you say
c = 10;
b = c;
let a = b;
c and b have the life span as fun have but a only have block span and if you try to access a by referencing it always show error but c and b are globally so they don't.You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.If you declare a variable without "let", it scopes the variable globally.So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a break-point). If you put a console log for a,b,c in that first function, all is well.But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a break-point in the second function), but the other two (or however many you add) are still available.
回答8:
Here are the 3 interesting aspects of variable declarations in JavaScript:
var restricts the scope of variable to the block in which it is defined. ('var' is for local scope.)
let allows temporary overriding of an external variable's value inside a block.
Simply declaring a variable without var or let will make the
variable global, regardless of where it is declared.
Here is a demo of let, which is the latest addition to the language:
// File name: let_demo.js
function first() {
a = b = 10
console.log("First function: a = " + a)
console.log("First function: a + b = " + (a + b))
}
function second() {
let a = 5
console.log("Second function: a = " + a)
console.log("Second function: a + b = " + (a + b))
}
first()
second()
console.log("Global: a = " + a)
console.log("Global: a + b = " + (a + b))
Output:
$ node let_demo.js
First function: a = 10
First function: a + b = 20
Second function: a = 5
Second function: a + b = 15
Global: a = 10
Global: a + b = 20
Explanation:
The variables a and b were delcared inside 'first()', without var or let keywords.
Therefore, a and b are global, and hence, are accessible throughout the program.
In function named 'second', the statement 'let a = 5' temporarily sets the value of 'a' to '5', within the scope of the function only.
Outside the scope of 'second()', I.E., in the global scope, the value of 'a' will be as defined earlier.