从原理角度分析var let const的区别

从原理角度分析var let const的区别

一、存储方式

  1. var

    1.1 变量的值是原始值

    会在栈内存中预分配内存空间,当语句被执行时,会将变量存储到该内存空间。

    1.2 变量的值是引用值

    会在堆内存里开辟一个内存空间存储实际值,在栈内存中会存储一个指向该堆内存的指针。

  2. let

    不会在栈内存里预分配内存空间。执行语句时,会在栈内存做一个检查,如果已经有相同变量名存在就会报错。

  3. const

    不会在栈内存里预分配内存空间。执行语句时,和let相同,会在栈内存检查是否存在相同变量名,存在则报错。

    不过,const存储的变量是不可以修改的:

    3.1 如果变量值是原始值,则无法修改该变量的值;

    3.2 如果变量值是引用值,则无法修改栈内存里分配的指针,但是可以修改指针指向的对象里面的属性。

可以看看下面的例子:

var num1 = 10;
var num1 = 20;
console.log(num1);	// 20

let num2 = 30;
let num2 = 40;	// Uncaught SyntaxError: Identifier 'num2' has already been declared

const num3 = 50;
num3 = 60;	// Uncaught TypeError: Assignment to constant variable

const obj1 = new Object();
const obj2 = new Object();
obj1 = obj2	// Uncaught TypeError: Assignment to constant variable

obj1.num4 = 70;
console.log(obj1.num4)	// 70
复制代码

二、区别

  1. 作用域

    1.1 使用var进行声明的变量,变量会自动添加到最接近的上下文。

    在函数中,最接近的上下文就是函数的局部上下文;在with语句中,最接近的上下文也是函数的局部上下文;如果变量未经声明就被初始化,则会被自动添加到全局上下文中。

    如以下例子所示:

    function add1(a, b) {
      var sum = a + b;
      return sum;
    }
    
    let result = add1(10, 20);
    console.log(result);	// 30
    
    function add2(a, b) {
      // 在这里不对sum进行声明,直接初始化
      sum = a + b
      return sum;
    }
    let result = add2(10, 20);
    console.log(result);	// 30
    console.log(sum);			// 30
    
    复制代码

    1.2 let的作用域是块级的。块级的作用域由最近的一对包含花括号{}界定。

    代码示例如下所示:

    while(true) {
      let a = 10
    }
    console.log(a)	// Uncaught ReferenceError: a is not defined
    复制代码
  2. 变量提升

    2.1 var声明会拿到函数或全局作用域的顶部,位于所有代码之前。声明的提升意味着会输出undefined而不是Reference Error,以下代码可以验证变量会被提升:

    console.log(name);	//undefined
    var name = 'aki';
    复制代码

    2.2 严格来讲,使用let声明变量时也会发生变量提升的现象,但由于存在“暂时性死区”,不能在声明之前使用let变量。因此,从写JavaScript的角度说,let的提升和var的提升是不一样的。

  3. const常量声明

    使用const声明的变量必须同时进行初始化;const赋值的引用值变量不能再被重新赋值为其他引用值,但对象的键不受限制。

    const num1;	// SyntaxError
    num1 = 10;
    
    const num2 = 20;
    num2 = 200;	// TypeError
    复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享