简述const、let、var的区别,练习用var实现let

903 阅读3分钟

const

  1. const声明一个只读变量(常量),声明后不允许改变(即栈内存的值和地址),所以const一旦声明就必须初始化
  2. JavaScript 的数据类型分为两类:原始值类型和对象(Object类型)
  • 对于原始值类型(undefined、null、true/false、number、string),值就保存在变量指向的那个内存地址(在栈中),因此 const 声明的原始值类型变量等同于常量
  • 对于对象类型(object,array,function等),变量指向的内存地址其实是保存了一个指向实际数据的指针,所以 const 只能保证指针是不可修改的,至于指针指向的数据结构是无法保证其不能被修改的(在堆中)
    const x = "111";
    console.log("x: ", x);
    x = "111111" // 报错了,不能赋值给常量

    const y = {
      value: "222"
    };
    console.log("修改前y: ", y);
    y.value = "333";
    console.log("修改后y: ", y);
    y = {} // 报错了,不能赋值给常量

image.png

let

  1. 块级作用域,在块外会被回收
  2. 不能重复声明
  3. let声明的变量在执行上下文创建阶段只会被创建,不会被初始化,因此对于执行阶段来说,如果在定义前使用则会报错,相当于使用了未被初始化的变量
    for (let x = 0; x < 4; x++) {
      console.log("let", x); // 变量正常输出
    }
    console.log("let", x); // 报错,提示x没有被定义

image.png

var

  1. 函数作用域,作用域是全局或者整个函数快的
  2. 可重复声明
  3. 实质是在全局对象里新建了一个属性
  4. var声明的变量在执行上下文创建阶段会被创建并初始化,因此对于执行阶段来说,可以在声明之前使用
  5. 变量提升
  • 由名称和对应值(undefined)组成一个变量对象的属性被创建并初始化
  • 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性
    // 通过两个例子理解var的变量提升到底干了个啥
    
    console.log(a); // undefined
    var a = 3;
    console.log(a); // 3
    
    // 以上可隐式理解为
    var a;
    console.log(a); // undefined
    a = 3;
    console.log(a); // 3
    
    -----------------------------------------
    
    var a = 12;
    function fn() {
      console.log(a); // undefined
      var a = 13;
    }
    fn();

    // 以上可以隐式的理解为
    // 执行fn时,会在fn里面形成执行上下文,
    // console.log(a) 会在函数这个上下文找到a,这里就是undefined
    var a = 12;
    function fn() {
      var a;
      console.log(a); // undefined
      a = 13;
    }
    fn();
    for (var y = 0; y < 4; y++) {
      setTimeout(function () {
        console.log("setTimeout y", y);
      }, 1000);
      console.log("var", y); // 变量正常输出
    }
    console.log("yyyy", y); // 由于var可使变量提升,所以打印出的值为for循环中最后输出的值

image.png

用var使用匿名函数实现let

    for (var z = 0; z < 4; z++) {
      (function f(a) {
        setTimeout(function () {
          console.log("var实现let", a);
        }, 1000);
      })(z);
    }

image.png

匿名函数(function (){})()

  • (function (){})是标准的函数定义,没有赋值给任何变量,没有名字,也叫匿名函数。
  • 匿名函数不能像普通函数那样随时随地调用,所以在匿名函数定义完后要立马调用他,后面的括号()就是运行该匿名函数。
  • 类似写法还有以下
    • ~function (){}()
    • -function (){}()
    • +function (){}()
    • void function (){}()
    • (function (){}())
    • (function (){})()
  • 括号()前面要求必须是个表达式
  • ~ - +符号就是把function (){}函数体转为函数表达式