局部变量
在函数体内用var声明的是局部变量,在函数结束即销毁:
<!DOCTYPE HTML>
<HTML>
<BODY>
</BODY>
<HEAD>
<meta charset="utf-8">
<script>
//console.log(x); //函数外不可见
myfun(); //函数执行
//console.log(x); //函数外不可见
/*函数声明*/
function myfun(){
var x=10;
console.log(x);
}
</script>
</HEAD>
</HTML>
输出
10
在函数体外尝试输出函数内定义的局部变量x会报错。
全局变量
首先,在函数体外声明使用的变量一定是全局变量,在页面关闭时才销毁:
<!DOCTYPE HTML>
<HTML>
<BODY>
</BODY>
<HEAD>
<meta charset="utf-8">
<script>
var y=20; //全局变量
console.log('y='+y);
myfun(); //调用函数
function myfun(){
var x=10; //局部变量
console.log('x='+x);
console.log('y='+y);
}
</script>
</HEAD>
</HTML>
输出
y=20
x=10
y=20
其次,没有使用var声明就直接使用的变量,不论在哪里都被视为全局变量:
<!DOCTYPE HTML>
<HTML>
<BODY>
</BODY>
<HEAD>
<meta charset="utf-8">
<script>
//console.log('y='+y); //函数调用之前这个变量还是不存在的
myfun(); //调用函数
console.log('y='+y); //函数调用以后全局变量y就存在了
function myfun(){
var x=10; //局部变量
y=20; // 全局变量
console.log('x='+x);
console.log('y='+y);
}
</script>
</HEAD>
</HTML>
输出
x=10
y=20
y=20
全局变量都是window的成员变量,所以上面的全局变量y其实也就是window.y
。
块级变量
let声明的块级变量只能在其声明的最小子块中使用,而不会去操作块外的同名变量。如果let不是在语句块里声明的,那么声明出来的变量作用域是全局的,但却并不是window的成员变量:
<!DOCTYPE HTML>
<HTML>
<BODY>
<p id='ok'></p>
</BODY>
<HEAD>
<meta charset="utf-8">
<script>
"use strict"; //目前在严格模式下才能用ES6的let声明和使用块级变量
let x=0; //这个块级变量x作用域是全局的
//var x=0; //实实在在的全局变量
myfun(); //调用函数
function myfun(){
let x=10; //只在myfun()里有效
//var x=10; //实实在在的局部变量
if(1===1){
let x=20; //只在这个if里有效
console.log(x); //输出这个if里的块级变量x看一下
}
console.log(x); //输出myfun()里的块级变量x看一下
}
console.log(window.x); //尝试访问window下的变量x
console.log(x); //访问全局作用域的块级变量x
</script>
</HEAD>
</HTML>
输出
20
10
undefined
0
一些有意思的现象
在声明块级变量后,又声明局部变量,会和这个块级变量冲突:
"use strict";
myfun();
function myfun(){
let x=10; //块级变量
if(1===1){
var x=20; //尝试声明局部变量
console.log(x);
}
console.log(x);
}
报错
Uncaught SyntaxError: Identifier 'x' has already been declared
如果是声明了局部变量之后,再声明并初始化一次,那么会覆盖掉前面的那个局部变量的值:
"use strict";
myfun();
function myfun(){
var x=10; //局部变量
if(1===1){
var x=20; //尝试重新初始化局部变量
console.log(x);
}
console.log(x);
}
输出
20
20
但是如果仅仅是重复声明,是不会改变这个局部变量的值的:
"use strict";
myfun();
function myfun(){
var x=10; //局部变量
if(1===1){
var x; //尝试重新声明局部变量,不初始化
console.log(x);
}
console.log(x);
}
输出
10
10
所以可以把初始化看成声明+赋值的过程(难道js里不分初始化记号和赋值号这样的说法吗),即对局部变量的重复声明无效,但是不报错:
"use strict";
myfun();
function myfun(){
var x=10; //局部变量
if(1===1){
var x; //尝试重新声明局部变量,不初始化
console.log(x+3);
}
console.log(x-3);
}