这几天修改别人的js,发现声明变量有的用var,有的用let,那它们有什么区别呢?
javascript中声明变量的方式有:var
、let
、const
1.var
(1)作用域:
整个函数范围内,或者是全局的
function func() { if (true) { var str = 'hello world'; } console.log(str); }
输出:
hello world
(2)允许在相同作用域内重复声明同一个变量
var var1 = 'var1 first.'; var var1 = 'var1 second.'; console.log(var1);
输出:
var1 second.
(3)var可以先使用,后声明
var1 = 'var1 first.'; var var1; console.log(var1);
输出:
var1 first.
(4)声明后未赋值
var var1; console.log(var1);
输出:
undefined
2.let
(1)作用域:
只在let命令所在的代码块内({})有效
function func() { if (true) { let str = 'hello world'; } console.log(str); }
报错:
Uncaught ReferenceError: str is not defined
(2)不允许在相同作用域内重复声明同一个变量
let var1 = 'var1 first.'; let var1 = 'var1 second.'; console.log(var1);
报错:
Uncaught SyntaxError: Identifier 'var1' has already been declared
(3)let必须先声明后使用
var1 = 'var1 first.';
let var1;
console.log(var1);
报错:
Uncaught ReferenceError: var1 is not defined
(4)声明后未赋值
let var1;
console.log(var1);
输出
undefined
3.const
const声明一个只读的常量
(1)作用域:
只在声明所在的块级作用域内有效
{ const PI = 3.1415; } console.log(PI);
报错:
Uncaught ReferenceError: PI is not defined
正确的使用位置
{ const PI = 3.1415; console.log(PI); }
输出:
3.1415
(2)声明之后值就不能改变
const PI = 3.1415;
PI=3;
报错:
Uncaught TypeError: Assignment to constant variable.
(3)声明后必须立即初始化
const PI; PI = 3.1415; console.log(PI);
报错:
Uncaught SyntaxError: Missing initializer in const declaration
(4)不允许在相同作用域内重复声明同一个变量的
const PI = 3.1415; console.log(PI); const PI = 3.1415926; console.log(PI);
报错:
Uncaught SyntaxError: Identifier 'PI' has already been declared
正确的用法
const PI = 3.1415; var s= 3*3*PI; console.log(s);
输出:
28.273500000000002
4.常见的面试题
var msg = ["This", "is", "a", "test"]; for (var i = 0; i < msg.length; i++) { console.log("outer:"+i); setTimeout(function() { console.log("index:" + i + ",msg:" + msg[i]); }, 0); }
输出:
outer:0
outer:1
outer:2
outer:3
index:4,msg:undefined
index:4,msg:undefined
index:4,msg:undefined
index:4,msg:undefined
原因:
setTimeout的执行方式是异步执行
JavaScript 是单线程的,遇到setTimeout后会另开一条线程
执行setTimeout里的代码时,同步代码for循环已经执行完成
整个循环中只有一个i
,i
被for
循环以及三个回调函数共用,循环结束后i=4,已经超出了原本数组的范围
把var 改成let
var msg = ["This", "is", "a", "test"]; for (let i = 0; i < msg.length; i++) { console.log("outer:"+i); setTimeout(function() { console.log("index:" + i + ",msg:" + msg[i]); }, 0); }
输出:
outer:0
outer:1
outer:2
outer:3
index:0,msg:This
index:1,msg:is
index:2,msg:a
index:3,msg:test
原因:
let所声明的变量,只在let
命令所在的代码块内有效,而且有暂时性死区的约束
暂时性死区:只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域, 不再受外部的影响