面试常考 | var let const 到底有什么区别 ?

1. 前言

从本篇博客起,小编将会不断的更新这个新的专栏 — 面试集合 更新一些常见的面试题,感兴趣的小伙伴点个订阅。
接下来的内容将会围绕下面这个表格进行讲解。

关键字 块级作用域 变量提升 重新赋值 声明同名变量 是否推荐使用
var
let
const

2. var

使用var声明变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境;如果初始化变量时没有使用var声明,该变量就会自动被添加到全局作用域,如下案例。

function add(num1,num2){
	// 函数作用域
	var sum = num1+num2;
	return sum ;
}
var result =add(10,20); // 30
alert(sum); // 由于不是有效的变脸因此会发生报错

以上代码的函数定义了一个名为sum的局部变量,该变量包含加法操作的结果。虽然结果值从函数中返回了,但变量sum在函数的外部是访问不到的,如果省略这个例子中的var关键字,那么add()执行完毕后,sum将可以被访问到。

function add(num1,num2){
	// 函数作用域
	sum = num1+num2;
	return sum ;
}
var result =add(10,20); // 30
alert(sum); // 输出 30

(1) var 块级作用域

javascrpit没有块级作用域常常会导致理解上面的困惑。在其它一些语言中由花括号“{}”封闭的代码都有自己的作用域,因而支持根据业务条件来定义变量。

// 全局作用域
var hello = "hello"

function fn(){
	// 函数作用域
}

{
	// 块级作用域
	var world = "world"
	// 按照常规外部是无法访问这个块级作用域的 和外界是隔离的
	// 但是 var 是没有块级作用域的 所以外部也能访问
}
console.log(world); // 输出 world

// 常见场景
 for(var i=0; i<5; i++){
      console.log('循环内部-->', i);
      // 这里是一个块级作用域
      // 也是一个块级作用域 上面是var声明的证明循环外部也能访问 相当于一个全局变量
      // 这里使用let 声明的话外面就无法访问
 }
 console.log(i); // 输出 5

 // 包括在if{}
 if(true){ 
 // 这也是一个块级作用域
 // 表达式是true的话这个代码块是会执行的 而var没有块级作用域所以外部能访问到
 // 如果是false的话这个代码块是不会执行的,但是由于var没有块级作用域下面还是会输出undefined
 // 不执行只是不会进行初始化 但是变量是已经声明了的
 var b="牛马"
 }
 console.log(b); // 输出 牛马

(2) var变量提升

变量提升是指无论 var 出现在一个作用域的哪个位置,这个声明都属于当前的整个作用域,在其中到处都可以访问到。注意只有变量声明才会提升,对变量赋值并不会提升。如下例所示

console.log(a);//在这之前根本没有声明过变量但是由于变量提升还是输出 undefined
var a = 1;

var b;
console.log(b);//变量声明了但是未进行初始化输出 undefined
b = 1;

// 而如果对未声明过的变量进行操作,就会报错
console.log(c);//c未声明过发生报错,Uncaught ReferenceError: b is not defined

(3) var 重新赋值

var关键字并不像 const 关键字,声明的变量初始化之后就不可以重新赋值了,var声明的变量是可以重新进行赋值的。

var hello = 2;
hello = 3;
alert(hello); // 3

(4) var 声明同名变量

为什么var可以重复声明,因为编辑器会在判断有已经声明的同名变量时忽略var,然后直接进行赋值。

//var 关键字可以声明同名变量,实际第二次声明是对第一次声明的变量重新赋值
var num = 10;
var num = 20;
console.log(num);  // 20

// 声明变量时也可先不对其进行初始化
var num1
num1=30
console.log(num1); // 输出 30

当执行上面的代码时,我们可以简单的理解为新变量分配一块儿内存,命名为num并赋值为1,但在运行的时候编译器与引擎还会进行两项额外的操作,判断变量是否已经声明
如果重复声明,则首先编译器会对代码进行分析拆解,从左至右遇见var a,则编译器会询问作用域是否已经存在叫a的变量了。如果不存在,则在作用域声明一个新的变量a,若已经存在,则忽略 var 继续向下编译,这时 num = 20(相当于重新赋值)被编译成可执行的代码供引擎使用。

// 值得注意的是
//var关键字可以重复声明同名变量,但是之前的变量时let或者const关键字声明的还是会发生报错
let num = 20 // 发出语法错误
var num = 20 // 发出语法错误
console.log(num); // 强行执行还是会发生报错

const num = 20 // 发出语法错误
var num = 20 // 发出语法错误
console.log(num); // 强行执行还是会发生报错

3. let

let是ES6新增的关键字,存在块级作用域,且声明的变量可以重新赋值,但是是不能使用let声明同名的变量的关于一些其他细节下面会介绍到,还是比较推荐使用。

(1) let 块级作用域

let是存在块级作用域的,即let 声明的变量只在 let 命令所在的代码块内有效,还是以上面的一个例子来演示。

// 全局作用域
let hello = "hello"

function fn(){
	// 函数作用域
}

{
	// 块级作用域
	let let_world ="world"
}
console.log(let_world); // 结果发生报错 因为let有块级作用域外部无法访问

// 常见场景
 for(let i=0; i<5; i++){
      console.log('循环内部-->', i);
      // 也是一个块级作用域 
 }
 console.log(i); // 发生报错

 // 包括在if{}
 if(true){ 
 // 这也是一个块级作用域
 // 表达式是true的话这个代码块是会执行的 而var没有块级作用域所以外部能访问到
 // 如果表达式是false的话这个代码块是不会执行的 由于let有块级作用域下面会直接报错
 	let b="牛马"
 }
 console.log(b); // 发生报错 因为let存在块级作用域 外部无法访问

(2) let 变量提升

let并不存在变量提升,即只有变量在当前作用域内声明后才可以访问,也并没有赋值提升。

console.log(a);//变量未声明 发生报错 ReferenceError
let a = 1;

var b;
console.log(b);// 声明了但是未初始化输出 undefined
b = 1;

(3) let 重新赋值

let关键字和var关键字一样,声明的变量都是可以进行重新赋值的

let a =1
a=2
console.log(a);  // 输出 2

// 声明时也可以先不用对其初始化
 let b
 b = 2
 console.log(b); // 输出 2

(4) let 声明同名变量

虽然let关键字声明的变量可以重新赋值但是,并不能声明同名的变量否则会发生报错

let a = 1;
// 会直接报出语法错误
let a = 2;//Uncaught SyntaxError: Identifier 'a' has already been declared

//let 关键字不能重复声明同名变量,即使之前是用var声明的也会报错
var num2 = 10;
let num2 = 20;  // Uncaught SyntaxError: Identifier 'num2' has already been declared 

4. const

const 是ES6新增的关键字,是用来声明一个常量的,其声明变量时必须对其进行初始化,标识符一般为大写,且初始化后值不允许修改,比较常用,关于其他细节下面会介绍到。

(1) const 块级作用域

const关键字和let关键字一样都有块级作用域,还是用上面的一个案例来演示

// 全局作用域
var HELLO = "hello"

function fn(){
	// 函数作用域
}

{
	// 块级作用域
	//  const 没有块级作用域所以外部无法访问
	const CONST_WORLD="world"
}
console.log(CONST_WORLD); // 结果发生报错


 // 包括在if{}
 if(true){ 
 // 这也是一个块级作用域
 // 表达式是true的话这个代码块是会执行的 而var没有块级作用域所以外部能访问到
 // 如果表达式是false的话这个代码块是不会执行的 因为const声明的变量没有块级作用域所以外部无法访问
 	const B="牛马"
 }
 console.log(B);  // 发生报错 当前作用域并没有这个变量

(2) const 变量提升

和let关键字一样const关键字是没有变量提升的,只有在当前作用域声明了才可以进行访问,否则将会发生报错,但是不同的是const关键字声明变量时必须对其进行初始化,且初始化后就不能对其值进行修改了。

console.log(A);//变量未声明 发生报错 ReferenceError
const A = 1;

const b; // 爆出语法错误
console.log(b); // 强行执行发生报错,声明变量时必须对其进行初始化
b = 1;

(3) const 重新赋值

重新赋值的特性感觉都不用过多介绍了,let,var都是用来声明变量的显然都是可以进行重新赋值的,而关键字const是用来定义一个常量或者若干个常量的,且在定于的时候必须进行初始化,且初始化完成后就不能够被修改了

// 错误写法 定义常量时必须进行初始化
const PI;
PI = "world";

// 常量值无法被修改(或者说是重新赋值)
cnost HELLO = "hello"  
HELLO = "world" // 爆出语法错误
consoel.log(hello) // 强行执行后发生报错 

但是并不是说常量的值就不能够被改变了,准确的说,是 const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。

// 下面代码都是可以正常执行的

// 创建常量对象
const CAR = {name:"小明", age:"180", hobby:"喝酒"};
// 修改属性:
CAR.hobby = "敲代码";
// 添加属性
CAR.like = "小红";
 
// 创建常量数组
const CARS = ["js", "html", "css"];
// 修改元素
CARS[0] = "java";
// 添加元素
CARS.push("go");

const 声明的变量如果是基本类型,那么不允许改变,如果是引用类型,那么只要不改变引用的地址就是可以的。也就是说其实const保证的并不是变量的值不动,而是变量指向的内存地址不得改动。

(4) const 声明同名变量

const关键字和let关键字一样是不允许声明同名的变量的

const X = 2;       // 发生语法错误
const x = 3;       // 发生语法错误

//const 关键字不能重复声明同名变量,即使之前是用var声明的也会报错
var Y = 2;         
const Y = 2;       
console.log(Y); // 发生报错
 
// 如果之前是let关键词定义的变量,也会发生报错
let Y1 = 2;         // 发生语法错误
const Y1 = 2;       // 发生语法错误
console.log(Y1); // 强行执行会发生报错

5.结尾

那么本篇博客的内容就到此结束了,不经感叹小编真是个够细的男人,如果有需要补充或者错误的地方还请各位读者姥爷们在评论区提出,小编一定及时对其进行修改,后续本专栏也将会推出更多的面试常考的知识点讲解,期待的小伙伴不妨点个订阅。
面试常考 | var let const 到底有什么区别 ?_第1张图片

你可能感兴趣的:(前端面试常考,面试,javascript,前端)