一、作用域
在说定义之前,先说一个作用域的问题,作用域又分函数作用域和块级作用域。
1、函数作用域
函数作用域呢,就是指函数内部,在函数内部中定义的东西在函数外无法访问,比如下面这段
function Test(){
var temp = '函数内变量';
}
//此处想要访问temp变量就访问不到
console.log(temp);
2、块级作用域
块级作用域,即大括号{}之间的区域,此处多是指以下几种情形
// 条件语句
if () {}
// switch语句
switch () {}
// for / while循环语句
for () {}
while () {}
// try...catch语句
try () catch (err) {}
// 单大括号
{}
二、var和let
之前已经说过了作用域了,那么这里直接说,var的作用域是函数作用域而let的作用域是块级作用域。
1、var
函数内部用var定义的变量仅在函数内部可以访问,在函数外部无法访问。就如下面这段代码所示
function Test() {
var temp = 5;
console.log('inside ' + temp);
}
Test();
console.log('outside ' + temp); // 此处会报错
最后一个log语句会报错提示temp变量没有被定义,因为你在函数外是访问不到函数内部用var定义的变量的。但是在{}内部,即块级作用域内用var定义的变量是可以跨越作用域被访问到的,下面这段代码就会正常的进行打印
if (true) {
var temp = 5;
console.log('inside ' + temp);
}
console.log('outside ' + temp); // 正常打印结果
2、let
{}块级作用域内部用let定义的变量仅在作用域内部可以访问,在作用域外部无法访问。就如下面这段代码所示
if (true) {
let temp = 5;
console.log('inside ' + temp);
}
console.log('outside ' + temp); // 此处会报错temp变量没有被定义
但是同样的在函数作用域内部用let定义的变量在函数外也是无法访问的,此处大致可以看出二者的关系应该为
3、变量提升和暂时死区
var声明的变量,无论实际声明的位置在何处,都会被视为声明在函数的顶部,如果不在函数内,则视为在全局作用域的顶部。而let和const则没有这个变量提升,当提前调用了let或const声明的变量(或常量)时,则会报错“不能在初始化之前访问”。例如下面的代码
console.log(temp); // 不会报错,打印unfined
var temp = 5;
console.log(temp); // 打印5
console.log(temp1); // 报错,“不能在初始化之前访问”
let temp1 = 5;
console.log(temp1); //不会执行,因为前面已经暂时性死区
为什么会这样呢?因为javascript引擎工作方式是先预解析,获取所有被声明的变量和函数,再一行行地执行,这样所有变量声明都会被提升到头部,这就是变量提升。
三、const
const,即为常量的定义,常量必须先声明再访问,与let一样不存在变量提升。常量声明时必须进行初始化,如const temp = 5;
,否则就会报错“const声明中缺少初始化式”。
1、const的不变
常量,顾名思义,对它进行了初始化之后是无法再进行改变的。
const temp = 5;
temp = 6; // 报错,“对常量变量的赋值”
2、const的变
这里的变不是说违反了上一条所说的。先看下面这段代码
const person = {
name: '韩梅梅',
age: 14
}
console.log(person);
person.age = 15;
console.log(person); // 此处打印结果可看出韩梅梅的年龄已经变为15岁
person = {
name: '李雷',
age: 16
}
console.log(person); // 报错,因为person为常量变量无法重新赋值
由此可以看出,我们改变的实际上并不是const声明的常量变量指向的对象,而是指向对象当中的某个属性。而对常量变量本身的重新赋值依旧是不被允许的,所以没毛病。
四、写在最后的一些话
这里是学习路上的一些记录备忘,所以难免会不够准确甚至错误。欢迎大家路过指正。