先简单的回顾一下在ES5里面的变量的声明:
1> var + 变量名
var test = "test"; //全局变量
function funOne(){
var a = 3; //局部变量
alert(a);
}
function funTwo(){
alert(test);
}
这里面test就是全局变量,a就是局部变量。
2> 没有使用var标示,直接给变量赋值,会默认这个变量为全局变量,例如:
test = "hello";
function foo(){
console.log(test);
}
foo(); //运行结果:“hello”
在上面的代码中,隐式的声明了全局变量test,所以才在foo方法中能访问变量test.
3> 使用window全局对象来什么变量,这样的变量都是全局变量;
window.test = "hello 3"; //全局变量
function foo(){
console.log(test);
}
foo();
上面的几种方法中,1,3是显示声明变量,2是隐式声明变量。
注意:
(1)全局变量变量保存在静态存储区,程序开始时就分配内存,结束时才释放内存,所以生命周期长;局部变量是动态分配,动态释放。所以,要合理声明变量,
减少不必要的开销,避免重复定义变量,覆盖先前定义的变量的危险。;
(2)当我们使用一个未声明的变量会报错,但是我们给一个未声明的变量赋值的话,不会报错,会隐式的声明一个全局变量。这点要注意;
(3)注意变量的生命周期:全局变量会在程序结束后被释放,局部变量在函数运行后被释放。
(4)变量声明提升:JavaScript引擎在运行的时候,会把所有的变量申明,提升到当前作用域的最顶部,函数的申明也会提升。举个简单的例子:
var test = "hello";
function foo(){
console.log("test"); //undefined
var test = "world"
}
foo();
上面的代码,执行foo函数会打印出undefined。这是因为在函数里申明了局部变量,遮盖了全局作用变量test。局部变量test的申明会被提升的函数作用域的最前面,也就是:
var test = "hello";
function foo(){
var test;
console.log("test"); //undefined
test = "world"
}
foo();
(5)申明,定义,初始化:申明是宣称这个变量名字的存在,定义是给这个变量名分配存储空间,初始化是给名字分配的存储空间赋值。
var test; //申明
test = "hello JS"; //定义并且赋值
(6)JS没有块级作用域
ES6
一、let命令
es6新增了let命令用来申明变量,和var类似,但是let申明的变量只在let命令所在的代码块内有效。
{
var a = "hello";
let b = "world";
}
console.log(a); //"hello"
console.log(b); //ReferenceError: b is not defined
用var和let申明的变量a,b。b报错,表明let申明的变量只在它所在的代码块中有效,这里的代码块即"{ }"中的代码。
使用let申明变量的时候需要注意以下几个问题:
(1)不存在变量提升:var申明的变量,在声明前使用不会报错,变量值为undefined,let申明的变量,在声明前使用,会报错(ReferenceError)
(2)暂时性死区:如果在区块中使用let或const,这个区块就对这些命令申明的变量形成封闭作用域,凡是在声明前使用这些变量都会报错。
(3)不允许重复申明:不允许在同一个作用域内,重复申明同一个变量,也不能在函数内部,重复申明参数第二次,后面会报错。
(4)块级作用域:let实际上位javaScript提供了块级作用域,块级作用域本质上是一个语句,将多个操作封装到一起,没有返回值,在块级作用域前加上do,可使其变为do表达式,会返回这个块级作用域的返回值。