js中的变量是松散类型的。
也就是说:
var msg;//注意:这个时候,msg的值是一个undefined
msg = '123';
msg = 123;
上面我们定义的msg变量,连续的两次进行赋值,一次是赋值为字符串,一次是数字,这个在js中是完全的合法的。
var 操作符定义的变量,会成为定义该变量作用域中的局部变量,也就是说,在该函数作用域的外边是无法访问该变量的,因为这个变量,在函数退出的时候就会被销毁。
也就是说:
function test(){
var msg = '123';
}
test();
console.log(msg);//报错
如果在函数里面省略var的话就会将函数里面的变量,定义为一个全局变量
function test(){
msg = '123';
}
test();
console.log(msg)//123
虽然咋一看,好象js中的变量也就那么回事
但是,js中的var 定义的变量存在一个变量提升的问题:
function test(){
console.log(msg)
var msg='123';
}
test();//undefined
注意,所谓的变量的提升,不是说将变量的定义和赋值都提升,而是将变量的定义个提升到作用域的顶部:
//在js中我们这样写
var msg = '123';
//在渲染引擎里面,会变成这样
var msg;//这个是定义变量的语句,提升的使它
msg = '123'//这个是赋值的语句
理解了变量的提升,也就理解了上面的test()的结果为什么是一个undefined
因为上面那一段代码,会被渲染引擎解释为:
function test(){
var msg;
console.log(msg);
msg='123';
}
test();//undefined
这就解释了为什么会是undefined,首先是var定义的变量存在提升的问题,其次是因为,定义了了却没赋值的变量,在js中,该变量的值是一个undefined;
console.log(msg1);//undefined
var msg1 = '123';
console.log(msg1);//123
function test(){
console.log(msg1);//undefined
var msg1 = '456';
console.log(msg1);//456
}
test();
上面的代码也就等价于
console.log(msg1);//undefined
var msg1 = '123';
console.log(msg1);//123
function test(){
var msg1;
console.log(msg1);//undefined
msg1 = '456';
console.log(msg1);//456
}
test();
上面这个代码的运行结果就是
- undefined
- 123
- undefined
- 456
这就是为什么后来会增加一个let关键字
let关键字的其中一个作用就是解决了这个问题
function test(){
console.log(msg)//因为没有了变量的提升,所以渲染引擎完全就不知道msg是一个什么东西
let msg = '123';
console.log(msg);
}
test();//直接报错
let msg = '123';
function test(){
console.log(msg)
}
test();//123 这个时候,变量变量的作用域就是全局
let关键字的另外一个作用就是定义块级作用域:
在原来var定义的变量的时候:
- js没有块级作用域的
- 也就是说,语句块中var定义的变量,与包含函数中的变量,共享一个作用域
function test(){
for(var i=0;i<2;i++){
}
console.log(i)
}
test()//2
之所以等于2,是因为在i等于1的时候,for循环的最后,会将i加上一个1.这里不重点讨论
上面的代码,在for循环的外边,我们没有定义一个变量i但是却能打印输出//2
这就是为什么说:语句块中var定义的变量,与包含函数中的变量,共享一个作用域
使用了let以后,就会定义一个块级作用域
function test(){
for(let i=0;i<2;i++){
}
console.log(i)
}
test()//报错
本人才疏学浅,要是有不对的地方,还希望各位能批评指导。