简介
说明
本文介绍JavaScript中的let,const,var的区别。
编程中建议使用let和const,不建议使用var。
let和const
let和const的特性基本是一致的,唯一区别是:const定义的变量不能被修改,let定义的变量可以被修改。
示例
const:下边这样会报错:Uncaught TypeError: Assignment to constant variable.
const a = 2;
a = 3;
let:下边这样不会报错
let a = 2;
a = 3;
作用域
let,const 声明的变量:有全局作用域、函数作用域、块级作用域。
var 声明的变量:只有全局作用域和函数作用域,没有块级作用域。(相当于大括号被忽略,变量影响到外部)
let
if (true) {
let a = true;
}
console.log(a);
结果
报错:Uncaught ReferenceError: test is not defined
var
if (true) {
var a = true;
}
console.log(a);
结果
输出:true
var间接支持块作用域的方法
之前,JavaScript 只有 var 这一种声明变量的方式,这种方式声明的变量没有块级作用域,程序员们就发明了一种模仿块级作用域的方法。这种方法被称为“立即调用函数表达式”(immediately-invoked function expressions,IIFE)。
如今,我们不应该再使用 IIFE 了,但是你可以在旧脚本中找到它们。
IIFE 写法1:
(function() {
console.log("Hello");
})();
这里创建了一个函数表达式并立即调用。因此,代码立即执行并拥有了自己的私有变量。
IIFE 写法2:
(function() {
console.log("Hello");
})();
IIFE 写法3:
(function() {
console.log("Hello");
}());
IIFE 写法4:
!function() {
console.log("Hello");
}();
IIFE 写法5:
+function() {
console.log("Hello");
}();
函数表达式被括号 (function {...}) 包裹起来,因为在 JavaScript 中,当主代码流遇"function" 时,会把它当成一个函数声明的开始。但函数声明必须有一个函数名,所以这样的代码会导致错误:
function() {
let a = "Hello";
console.log(a);
}();
结果
报错:Uncaught SyntaxError: Function statements require a function name
加一个名字仍然不行,因为 JavaScript 不允许立即调用函数声明:
function go() {
}();
结果
报错:Uncaught SyntaxError: Unexpected token ')'
因此,需要使用圆括号把该函数表达式包起来,以告诉 JavaScript,这个函数是在另一个表达式的下文中创建的,因此它是一个函数表达式:它不需要函数名,可以立即调用。
重新声明
let和const:不可以在同一作用域下声明两次。
var:可以在同一作用域下声明两次。
let
let a = 3;
let a = 4;
console.log(a);
结果
报错:Uncaught SyntaxError: Identifier 'a' has already been declared
var
var a = 3;
var a = 4;
console.log(a);
结果
输出:4
声明前使用
简介
let和const:不可以在声明前使用。
var:可以在声明前使用。
var的提升
当函数开始的时候,就会处理 var 声明(脚本启动对应全局变量)。
换言之, var 声明的变量会在函数开头被定义,与它在代码中定义的位置无关(这里不考虑定义在嵌套函数中的情况)。
这种行为称为“提升”(英文为 “hoisting” 或 “raising”),因为所有的 var 都被“提升”到了函
数的顶部。
示例
let示例
function sayHi() {
a = "Hello";
console.log(a);
let a;
}
sayHi();
结果:
报错:Uncaught ReferenceError: Cannot access 'a' before initialization
先使用后声明
function sayHi() {
a = "Hello";
console.log(a);
var a;
}
sayHi();
结果
输出:Hello
与下边这两种写法是一样的:
写法1:先声明后使用
function sayHi() {
var a;
a = "Hello";
console.log(a);
}
sayHi();
写法2:先使用,后在块内声明
function sayHi() {
a = "Hello";
if (false) {
var a;
}
console.log(a);
}
sayHi();
在这个例子中, if (false) 分支永远都不会执行,但没关系,它里面的 var 在函数刚开始时就被处理了,所以在执行 (*) 那行代码时,变量是存在的。
var赋值不会提升
var声明会被提升,但是赋值不会。
示例
function sayHi() {
console.log(a);
var a = "Hello";
}
sayHi();
结果
输出:undefined
详解
var a = "Hello" 这行代码包含两个行为:
1. 使用 var 声明变量
2. 使用 = 给变量赋值。
声明在函数刚开始执行的时候(“提升”)就被处理了,但是赋值操作始终是在它出现的地方才起作用。所以这段代码实际上是这样工作的:
function sayHi() {
var a; // 在函数刚开始时进行变量声明
console.log(a); // undefined
a = "Hello"; // 赋值(当程序执行到这一行时)
}
sayHi();
因为所有的 var 声明都是在函数开头处理的,我们可以在任何地方引用它们。但在它们被赋值之前都是 undefined。
上面例子中 console.log 不会报错,因为变量 phrase 是存在的。但是它还没有被赋值,所以显示 undefiend 。