C/C++教程

let const var 的区别

本文主要是介绍let const var 的区别,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

var let const 的特性和区别

var:存在变量提升;不存在块级作用域(全局变量);可重复声明变量.可重新赋值;

let:不存在变量提升,存在块级作用域(局部变量);不可重复声明,可重新赋值。

const:不存在变量提升;存在块级作用域(是局部变量,只能在代码块中起作用。不可重复声明,不可重新赋值。

let的基本用法

1.作用域

使用var操作符定义的变量会成为包含它函数的局部变量,例如使用var在一个函数的内部定义一个变量,就意味着该变量在函数退出时被销毁。

1 function test() { 
2 var message = "hi";//局部
3   }
4 test();
5 console.log(message);//error

var声明的范围是函数作用域,而let声明的范围时块作用域。

if (true) {
var message = "hi";
console.log(message);//hi
}
console.log(message);//hi

if (true) {
let message = "hi";
console.log(message);//hi
}
console.log(message);//error

message变量之所以不能在if块外部被引用,是因为他的作用域仅限于该块内部。块作用域是函数作用域的子集。因此适用于var的作用域限制,同样适合于let。

2.块级作用域变量

1 a = 0;//全局变量
2 console.log(window.a)//0
3 let b = 1;//块级作用域变量。
4 console.log(window.b)//undifidend

 3.for循环

var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
  console.log(i);
  };
}
a[6]();//10

 

 上面函数中,变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i,每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console。log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,所以输出就是10。

如果使用let,声明的变量仅在块级作用域内有效,最后输出的就是6。

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function() {
  console.log(i);
  };
}
a[6]();//6

 

上面代码中,变量i是let声明的,当前的i只是在本轮循环中有效,所以每一次循环都创建一个块级作用域,所以最后输出的是6。

另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父级作用域,而循环体内部是一个单独的子作用域。

1 for (let i = 0; i<3; i++) {
2 let i = 'abc';
3 console.log(i);
4 }//abc*3

 

上面代码正常运行,输出三次abc。这表明函数内部的变量i与循环体i不在同一个作用域。

2.不允许重复声明

let 不允许在相同的作用域下,重复声明同一个变量。

function() {
let a = 0;
var a= 0;
}//报错

function () {
let a = 0;
let a = 2;
}//报错

 

因此,不能再函数内部重复声明变量。

function func (arg) {
let arg;//报错
}

function func (arg) {
  {
    let arg;//不报错
  }
}

 

3.不存在变量提升

var 命令会发生变量提升现象,即变量可以在声明之前使用,值为undefidend。这种现象多多少少是有点奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

为了纠正这种现象,let 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

//var 
console.log(foo);//输出undefidend
var foo = 2;

//let
console.log(a);//ReferenceError
let a = 1;

 

4.暂时性死区

从let块级作用域开始,到初始化位置,称作暂时性死区,对于变量的暂存死去中使用的变量会报错ReferenceError。

1 var tmp = 1;
2 if (true) {
3   tmp = 2;
4   let tmp;//ReferenceError
5 }

 

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6规定,如果区块中存在let和const命令,这个取快对这些命令声明的变量,从一开始就形成了封闭作用域,凡是在声明之前就是用发这些变量,就会报错。

const

const是constant(常量)的缩写,const和let一样也是用来声明变量的,但是const是专门用于声明一个只读常量的,顾名思义,常量的值是不可改变的。const一旦声明,常量的值就不可改变。

1 const Name = '张三‘;
2 Name = '李四’;//报错,常量不能修改

 

与let一样,只在块级作用域起作用。

if(1) {
const Name = 'zs';
}
alert(Name);//报错

 

与let一样,不存在变量提升,必须先声明后使用。

if(1) {
alert(Name);//报错
const Name = ‘贤主’;
}

 

与let一样,不可重复声明一个相同的变量。

var Name = '贤主‘;
const Name = '蜘蛛侠’;//报错

 

声明后必须赋值

const Name;//报错

 

常量是一个对象 传址赋值

1 const person = {“name”: “贤主”};
2 person.name = "老师";
3 person.age = "18";
4 console.log(person);//{name:老师,age:18}

 

怎么常量person好像被修改了,name改变了,还添加了age,怎么没有报错?还正常输出,不是说常量不可改变的吗?

这个时候我们先引入一个概念,在赋值的过程中,我们可以分为传值赋值和传址赋值,这里我们用到了传址赋值,什么叫传址赋值?

传址:在赋值过程中,变量实际上存储的是数据的地址(对数据的引用),而不是原始数据或者数据的拷贝。

用const来声明一个对象类型的常量,就是传址赋值,而不可修改的是对象的内存中的地址,而不是对象本身,所以这就解释了干菜这段代码为什么不会报错,而是正常输出了。

因为修改的不是person本身,修改的是name属性和增加一个属性age,而地址没有变,也不可变。没有违背常量不可改变的约定。但是如果:

const person = {"name":"张三”};
person.age = 20;
console.log(person);//{name:张三,age:20}
person = {};//报错 给常量person赋值

 

这篇关于let const var 的区别的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!