var
语法格式:
var a=2;
var声明的变量具有如下几个特征:
1.变量提升:变量声明无论出现在代码的任何位置,都会在任何代码执行之前处理。即可以先调用再声明。
(提升的是var a而不是a=2)
2.函数提升:JavaScript会将全局函数提升到<script…/>元素的顶部定义。也就是说,在同一个<script……/>元素内,JavaScript允许先调用函数,然后在后面再定义函数,后面运行时会自动将函数的声明提到顶部,也就是调用它之前,这样就相当于提前声明了该函数。
3.作用域:var变量没有块作用域。像if语句,for循环语句,都不会创建一个新的作用域,而函数会创建新的作用域,
4.给一个非声明变量赋值会隐式创建一个全局变量(全局object的一个属性),而该全局变量会自动添加全局window对象的属性。
5.如果不初始化,输出undefined。
注:函数提升要比变量提升的优先级要高一些,且不会被变量声明覆盖,但是会被变量赋值之后覆盖。
说明:
1.使用var声明变量,在方法内部是局部变量,在方法外部是全局变量
2.没有使用var声明的变量,在方法内部或外部都是全局变量,但如果是在方法内部声明,在方法外部使用之前需要先调用方法,告知系统声明了全局变量后方可在方法外部使用。
let
引入let的原因正是var的局限性,相比于var,let有以下几点优势:
1.作用域
let
允许声明一个作用域被限制在块级中的变量、语句或者表达式。使用let定义的变量要等到程序流执行到定义变量的代码行时才会装载。
<script type="text/javascript">
var name = 'yeeku'
function func()
{
// 下面的name不存在,因此程序导致错误
console.log(name);
let name = 'fkit';
console.log(name);
}
func();
</script>
上面程序先定义了一个全局的name变量,接下来程序在fun()函数中使用了let定义了同名的name变量,此时局部变量name会覆盖全局的name变量。但由于let定义的变量不会提前装载,因此在使用let定义局部变量name之前访问name变量会导致错误——如果是用var声明,则会变量提升(但此时的var没有赋值),则会先输出undefined,再输出局部变量name的值。
<script type="text/javascript">
for (let i = 0; i < 10 ; i++)
{
console.log(i);
}
// 报错:Uncaught ReferenceError: i is not defined
console.log("循环体之外:" + i);
</script>
使用let定义循环计数器,这样该循环计数器 i 将只在for循环中有效,因此程序在循环体之外访问 i 变量时候便会出错。如果将for循环中的 let 改为 var,那么在循环体中定义的 i 变量的作用域将会扩散到循环体之外。
2.用var定义的全局变量不会变成windows对象的属性。
<script type="text/javascript">
let name = 'yeeku';
console.log(name); //输出yeeku
console.log(window.name); // window.name不存在
</script>
用var定义的全局变量不会变成windows对象的属性,因此上面程序访问window.name时将看不到任何输出。
const
- 使用const定义的常量只能在定义时指定初始值。
- 使用const声明常量以后不允许改变常量值。
- 常量不能和它所在作用域内其它变量或者函数拥有相同名称。
const MAX_AGE=120;//正确
MAX_AGE=120;//错误
const MAX_AGE;//错误
MAX_AGE++;//错误