• var let const 区别


    一句话,let和const是var的改良版,能用const就不用let, 能用let就不用var。
    一、var的缺陷,先来看看使用var定义变量会有哪些问题:
    1.var不是块级作用域,下面的代码循环已经结束了,却还可以访问到变量test,可能会引起bug

    1. for(var i=0;i<10;i++){
    2. var test = i;
    3. }
    4. console.log(test);//9
    5. console.log(i)//10 用来记数的变量也可以访问, 无意中就污染了全局变量

    2.var定义的变量,有变量提升,变量提升,会对程序的维护带来困扰。

    1. if(true){
    2. console.log('执行了');
    3. }else{
    4. console.log('没执行');
    5. var j = 2;
    6. }
    7. console.log(j); //输出undefined 定义变量j的代码虽然没有执行,但是却依然不会报错

    3.var定义的变量,不会为异步任务单独绑定变量,下面这段代码,本意是让它每隔一段时间输出0-9,结果却输出了10个10

    1. for (var i = 0; i < 3; i++) {
    2. setTimeout(function () {
    3. console.log(i)
    4. }, 1000);
    5. }

    4.var定义的变量,可以重复定义,这样就显得非常的随意松散

    1. var a =1;
    2. var a =2;
    3. console.log(a);//输出后面定义的2

    二、let和const就是ES6针对以上问题提出的解决方案,let和var的区别具体如下:
    1.let声明的变量是块级作用域的,这个特性解决了原来使用var容易污染全局变量的弊端。

    1. for(let i=0;i<10;i++){
    2. let test = i;
    3. }
    4. console.log(i);//Uncaught ReferenceError: i is not defined
    5. console.log(test)//Uncaught ReferenceError: test is not defined

    2.let声明的变量不存在变量提升,从let的块级作用域开始,到初始化位置,称作“暂存死区”,对于变量的暂存死区中使用变量会报Reference错误。这个特性就使得我们先定义变量再使用的变量,避免了var变量提升带来的难以查找的bug,也增强了代码的可读性。(也有文章认为let和const是有变量提升的,但是从结果上我们直接把let和const理解成没有变量提升是正确的。)

    1. //使用var
    2. console.log(i); // 输出undefined
    3. var i = 2;
    4. //使用let
    5. console.log(j);
    6. let j =10; //Uncaught ReferenceError: Cannot access 'j' before initialization

    3.var可以重复定义变量,而let不可以,使得定义变量不再像var那么随意

    1. //使用var
    2. var a = 1;
    3. var a = 2;
    4. console.log(a); // var可以重复定义,输出2
    5. //使用let
    6. let i =1;
    7. let i =2;
    8. console.log(i);// let不能重复定义, Uncaught SyntaxError: Identifier 'i' has already been declared

    4.var定义的全局变量属于顶层对象,而let、const声明的全局变量属于顶层对象,这也很容易理解, 因为let的设计初衷就是块级作用域变量,不污染全局变量,显得自由灵活安全。以浏览器为例:

    1. var a = 0;
    2. console.log(window.a) // 0
    3. let b = 1;
    4. console.log(window.b) // undefined

    三、以上let具有的特性,const都有,const和let的区别如下:
    1.const在声明常量的时候, 一定要初始化一个值:

    1. const a=1; //正确
    2. const b = 1;
    3. b = 5; //TypeError: Assignment to constant variable.
    4. const c; //SyntaxError: Missing initializer in const declaration

    2.const定义的常量值不允许修改,

    1. const a = 0;
    2. a = 1; // TypeError: Assignment to constant variabl

    但是如果常量的类型为复杂类型(对象、数组等)时,对于常量值本身的操作是可以的, 因为const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。

    1. const a = {};
    2. a.name='小明'
    3. console.log(a);
    4. a = {name:'小明'};
    5. console.log(a);

    四、总结
    1.let和const声明的变量时块级作用域,避免了无意中全局变量污染,更加的灵活安全。另一个好处就是在循环语句中,let关键字为每次循环绑定单独绑定一个变量。
    2.let和const没有变量提升,提高了代码的可维护性。
    3.let和const不可以重复定义变量,修复var可以重复定义变量,使得变量的定义不再随意任性。
    4.let和const定义的变量不属于顶层对象。目的也是为了让变量定义更加自由灵活安全。
    5.const声明一个常量的时候,一定要赋值。
    6.const声明的常量并非真正意义上的常量,只保证变量名指向的地址不变,并不保证该地址的数据不变。
    五、拓展
    1.对于以下代码,改如何改正

    1. //本意是要输出0-9,这段代码却输出1010
    2. for (var i = 0; i < 10; i++) {
    3. setTimeout(function () {
    4. console.log(i)
    5. }, 1000);
    6. }

    解析:在js中先执行同步任务,再执行异步任务,setTimeout里面的代码是异步任务,等到执行时,var声明的变量i已经是10了。
    解法1,利用setTimeout函数的第三个参数把i单独绑定

    1. for (var i = 0; i < 10; i++) {
    2. setTimeout(function (i) {
    3. console.log(i)
    4. }, 1000, i);
    5. }

    解法2,利用闭包强制让setTimeout记住变量i

    1. (function(i){
    2. setTimeout(function () {
    3. console.log(i)
    4. }, 1000)
    5. })(i);

    解法3,利用let关键字

    1. for (let i = 0; i < 10; i++) {
    2. setTimeout(function () {
    3. console.log(i)
    4. }, 1000)
    5. }

    2.对于以下代码,本意是要每隔1秒输出0-9,但这段代码的效果却是1秒钟后,同时输出了0-9,如何修正?

    1. for (let i = 0; i < 10; i++) {
    2. setTimeout(function () {
    3. console.log(i)
    4. }, 1000)
    5. }

    解析:在js中先执行同步任务,再执行异步任务,setTimeout函数的第二参数,相对的是同步任务结束的那一刻, 而不是上一个异步任务结束的那一刻,所以,修正的方法是动态改变第二个参数。

    1. for (let i = 0; i < 10; i++) {
    2. setTimeout(function () {
    3. console.log(i)
    4. }, 1000*i)
    5. }
  • 相关阅读:
    保护数据安全:如何免受.kann勒索病毒的影响
    【音视频开发之起始】
    大厂程序员:杭州小公司给不了40k?网友群嘲
    jmeter性能测试使用梯度测试的方法
    【python】类方法、property类属性、单例模式
    代码检视的新姿势!在IDEA中得到沉浸式Code Review新体验
    史上最全 Zuul网关鉴权 范文
    哪些场景需要额外注意线程安全问题
    WSL2环境下Debian 12的Docker安装与配置
    Cesium 三维模型使用 blender 调整位置、坐标轴、比例等
  • 原文地址:https://blog.csdn.net/W859265708/article/details/127778591