var、let、const三者间的区别

本文主要对比了ES5中的var和ES6中的let、const的区别。var没有块级作用域,存在变量提升,而let有块级作用域并存在暂时性死区。let不允许重复声明,不能作为全局变量的属性调用。const则是一个不可变的let,其值不能改变,但对象或数组的属性和元素可以修改。

主要是var和let两者的区别,const放在最后说

1.var是ES5中的,let是ES6中的

ES5不存在块级作用域的概念,只有全局作用域和函数作用域。在ES6之前,解决这个问题主要靠闭包(closure)


闭包指的是有权访问另一个函数作用域中变量的函数,常见的方式就是在函数中创建函数,借此突破作用链域。

function say666(){
      var num =665;
      var sayalert = function(){
        alert(num)
      }
      num++;
      return sayalert
    }

    var a = say666()
    a()
  }

因为say666()内部函数的执行需要依赖say666()中的变量,所以js垃圾回收机制GC不会回收say666的资源

在ES6中,用let代替var,因为let只有块级作用域的概念,由 { } 包括起来,if语句和for语句里面的{ }也属于块级作用域。

2.var变量未声明是undefined,let变量未声明会报ReferenceError错误

var变量即使调用在前,声明在后,也不会报错,因为存在变量提升,即在JS中函数及变量的声明都会被提至顶部。let变量在声明前,都不可用,即暂时死亡(temporal dead)

TDZ(暂时性死区):只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
   tmp = 'abc'; // ReferenceError
   let tmp;
}

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

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

3.let不允许重复声明

{
	let a;
	let a;//'a' has already been declared
}
{
	var a;
	var a;//没问题,var可以重复声明
}
{
	var a;
	let a;//'a' has already been declared
}
{
	let a;
	var a;//'a' has already been declared
}

4.let不能作为全局变量的属性调用,而var可以

ES5中全局对象的属性与全局变量基本是等价的

ES6 中做了严格的区分:
使用 var 和 function 声明的全局变量依旧作为全局对象的属性,
使用 let, const 命令声明的全局变量不属于全局对象的属性

关于全局变量的补充——

var可以作为全局变量挂载到window上,即this,且var定义变量不能使用delete删除,而window可以

  var a = 2;
  this.c = 3;
  delete a;
  delete c;
  console.log(this.a)//2
  console.log(this.c)//undefined

var有变量提升,window没有

 console.log(a)//undefined
 var a = 2;
 console.log(c)// c is not defined
 window.c=2;

函数内部定义的var变量,在外层访问不到,因为var只有全局和函数作用域。在函数内部使用var定义的变量在外部不能访问到,而window能访问到。

 function test(){
	var a = 2;
	this.c = 2;
}
test();
console.log(this.c)//2
console.log(a)//a is not defined

5.const简单来说就是不能改变的let

const要初始化,如

const a = 10
const a //Const declarations require an initialization value 

简单数据类型如此,对象或数组类型也是一样
只不过const保存的是指向对象或数组的指针,变量指向的是内存地址

<think>好的,我现在需要回答用户关于JavaScript中letvarconst关键字的区别的问题。首先,我得回忆一下这三者的主要区别。根据用户提供的引用内容,我应该从作用域、变量提升、重新赋值以及块级作用域等方面展开。 首先,var的作用域是函数级的,而letconst是块级作用域。这意味着用var声明的变量在函数内部都有效,而letconst只在最近的{}块内有效。例如,在for循环中使用var可能会导致意外的结果,因为变量会泄露到外部作用域。 然后是变量提升的问题。var声明的变量会被提升到作用域的顶部,即使赋值在后面,变量也会存在但值为undefined。而letconst虽然也存在提升,但由于暂时性死区的限制,不能在声明前使用,否则会报错。这一点需要特别说明,避免用户混淆。 接下来是重新赋值。varlet声明的变量可以重新赋值,但const用于声明常量,一旦赋值后不可更改。不过需要注意的是,如果const声明的是对象,虽然不能重新赋值,但对象的属性可以修改。这部分可能需要举例说明,让用户更清楚。 另外,全局作用域下的var变量会成为全局对象的属性,比如window对象,而letconst不会。这也是一个区别点,可能影响代码的兼容性和行为。 现在要确保回答结构清晰,分点说明每个关键点,并给出示例代码。同时,根据用户的引用,需要正确引用来源,比如引用[1]、[2]、[3]中的内容,并在适当的位置添加引用标识。例如,在讨论作用域时引用[1]和[2],在总结时引用[3]。 还需要检查是否有遗漏的区别点,比如重复声明的问题。var允许重复声明同一个变量,而letconst不允许,这可能导致错误,需要提醒用户注意。 最后,生成相关问题,可能涉及实际使用场景、如何选择合适的关键字、历史背景等,帮助用户进一步理解。 需要确保回答中的LaTeX格式正确,所有行内数学表达式用$...$,独立公式用$$...$$,但当前问题不涉及数学公式,所以可能不需要使用。但如果有示例代码,需要用代码块包裹,并正确标注语言类型,如JavaScript。 可能还需要注意用户提供的引用内容中有一些是关于快速排序的示例,但当前问题与变量声明相关,所以应专注于引用中关于varletconst的部分。确保引用的正确对应,避免混淆。 总结回答的结构应该如下: 1. 作用域差异 2. 变量提升与暂时性死区 3. 重新赋值与常量 4. 全局对象属性 5. 重复声明 6. 示例代码对比 7. 总结与建议 每个部分需要简明扼要,用用户容易理解的语言,避免过于技术性的术语,必要时用例子说明。例如,在作用域部分,可以用if块中的变量声明来展示varlet的不同行为。 现在开始组织内容,确保每个区别点都涵盖,并正确引用提供的资料。同时,生成的相关问题要围绕主题,帮助用户深入理解,例如如何选择声明方式、ES6引入letconst的原因等。</think>### JavaScript中`let`、`var`和`const`的区别 #### 1. **作用域规则** - **`var`**:具有**函数作用域**或**全局作用域**。在函数内声明的`var`变量仅在该函数内有效,而全局作用域下声明的`var`变量会成为全局对象(如浏览器中的`window`)的属性[^1][^2]。 ```javascript function example() { if (true) { var x = 10; // 函数作用域 } console.log(x); // 输出10(if块外仍可访问) } ``` - **`let`/`const`**:具有**块级作用域**(`{}`内的范围)。在块内声明的变量仅在块内有效[^1][^3]。 ```javascript if (true) { let y = 20; const z = 30; } console.log(y); // 报错:y未定义 console.log(z); // 报错:z未定义 ``` #### 2. **变量提升(Hoisting)** - **`var`**:变量声明会被提升到作用域顶部,但**赋值不提升**。变量在声明前访问会得到`undefined`。 ```javascript console.log(a); // 输出undefined var a = 5; ``` - **`let`/`const`**:存在**暂时性死区**(TDZ),声明前访问会报错。虽然声明会被提升,但无法在初始化前使用。 ```javascript console.log(b); // 报错:Cannot access 'b' before initialization let b = 10; ``` #### 3. **重新赋值与重复声明** - **`var`**:可以**重复声明**同一变量,且允许重新赋值。 ```javascript var c = 1; var c = 2; // 合法 c = 3; // 合法 ``` - **`let`**:不可重复声明,但允许重新赋值。 ```javascript let d = 1; let d = 2; // 报错:Identifier 'd' has already been declared d = 3; // 合法 ``` - **`const`**:声明时必须初始化,且**不可重新赋值**,也不可重复声明。但若声明的是对象,其属性可修改[^3]。 ```javascript const e = { name: "Alice" }; e.name = "Bob"; // 合法 e = {}; // 报错:Assignment to constant variable ``` #### 4. **全局作用域下的行为** - **`var`**:在全局作用域声明时,会成为全局对象的属性(如`window.varName`)。 - **`let`/`const`**:不会添加到全局对象,但仍可在全局作用域使用。 #### 5. **使用建议** - 优先使用`const`声明常量或不需要重新赋值的变量。 - 使用`let`替代`var`以避免作用域问题。 - 仅在需要兼容旧代码时使用`var`。 --- ### 示例代码对比 ```javascript // var的变量提升与作用域问题 function varExample() { console.log(f); // undefined(变量提升) var f = "Hello"; if (true) { var f = "World"; // 覆盖外部f } console.log(f); // "World" } // let的块级作用域 function letExample() { let g = "Hello"; if (true) { let g = "World"; // 独立作用域 console.log(g); // "World" } console.log(g); // "Hello" } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值