一、区别
简述:
- var声明变量存在变量提升,let和const不存在变量提升
- let、const都是块级局部变量
- 同一作用域下let和const不能声明同名变量,而var可以
详述:
- var 定义变量,没有块的概念,可以跨块访问,但不能跨函数访问,不初始化会出现undefined,不会报错;有变量提升。
- let定义变量,只能在当前块级作用域里访问,也不能跨函数访问,对函数外部无影响;无变量提升。
- const定义常量,只能在当前块级作用域里访问,也不能跨函数访问,使用时必须初始化(即必须赋值),而且不能修改(引用数据类型,如指向的对象,即内存地址不能修改,但是能修改里面的属性);无变量提升。
二、const let var具体区别
- const 在声明变量时必须初始化(声明变量的同时并赋值即初始化),var 和 let 则不用
// const 在声明变量时必须初始化(声明变量的同时并赋值即初始化)
// 1、var
var a;
a = 1;
console.log(a) // 可以打印出 1
// 2、const
const b;
b = 2;
console.log(b) // html:43 报错 Uncaught SyntaxError: Missing initializer in const declaration
// 3、let
let c;
c = 3;
console.log(c) // 可以打印出 3
- 修改值(基本数据类型和引用数据类型)
修改基本数据类型值
// 1、var
var aa = 1;
aa = 2;
console.log(aa) // 打印出 2, 证明了可以修改
// 2、let
let bb = 1;
bb = 2;
console.log(bb) // 打印出 2, 证明了可以修改
// 3、const
const cc = 1;
cc = 2;
console.log(c) // 报错 Uncaught TypeError: Assignment to constant variable
-------------------------------------分割线--------------------------------------------------
12123123123131
修改引用(复杂)数据类型
// # 修改引用数据类型
const obj = {
name: '张三',
age: 18
}
obj.sex = '男'
obj.name = '李四'
console.log(obj) // 引用数据类型可以修改 打印出 {name: "李四", age: 18, sex: "男"}
// 修改数组的元素
const TEAM = ['1', '2', '3' , '4']
TEAM.push('5')
console.log(TEAM) // ["1", "2", "3", "4", "5"]
- 是否存在变量提升
// 变量提升
// 1、var
aaa = 1;
var aaa;
console.log(aaa) // 可以打印出 1,证明有变量提升
// 2、let
bbb = 1;
let bbb;
console.log(bbb) // 报错 Uncaught ReferenceError: Cannot access 'bbb' before initialization
// 3、const
ccc = 1;
const ccc; // 这一行就已经报错 Uncaught SyntaxError: Missing initializer in const declaration
console.log(ccc)
-
块级作用域
三、块级作用域
在ES6 之前, JavaScript中有三种作用域:
1. 全局作用域
2. 函数作用域
3. eval作用域
以上作用域内声明的变量或方法只在当前作用域内有效, 在其他作用域内引用则会返回 undefined;
而ES6则新增了一个作用域: 块级作用域
块级作用域可以简单理解为是: 包在大括号{}里面的内容, 它可以自成一个作用域, 但ES5中也有大括号, 可ES5中并没有块级作用域, 这时该怎样判断 {} 是否具有块级作用域的特点?
这时就得用到 let 和 const
因此, 可以将块级作用域理解为: 使用let和const声明的变量, 只在当前大阔号内生效, 由此构建出了 块级作用域 这么个东西.
这里的 "大括号内" 主要指的下面几种情况:
// 条件语句
if () {}
// switch语句
switch () {}
// for / while循环语句
for () {}
while () {}
// try...catch语句
try () catch (err) {}
// 单大括号
{}
注意: 对象的大括号内不是一个块级作用域, 因为它里面不能直接声明变量;
四、案例、应用
let
非常适合用于 for
循环内部的块级作用域。JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域,用let声明的变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。看一个常见的面试题目:
for (var i = 0; i <10; i++) {
setTimeout(function() { // 同步注册回调函数到 异步的 宏任务队列。
console.log(i); // 执行此代码时,同步代码for循环已经执行完成
}, 0);
}
// 输出结果
10 共10个
// 这里面的知识点: JS的事件循环机制,setTimeout的机制等
如果把 var
改成 let
声明:
// i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。
for (let i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // i 是循环体内局部作用域,不受外界影响。
}, 0);
}
// 输出结果:
0 1 2 3 4 5 6 7 8 9
案例
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
console.log('第' + (i + 1) + '个被点击');
};
}
输出结果:
点击哪一个button则会对应打印出console日志,如:第1个被点击了
ps:这个案例相当于在for循环中形成了闭包
对应的把 let 改成 var:
var btns = document.getElementsByTagName('button');
for (var i = 0; i < btns.length; i++) {
(function a(i) {
btns[i].onclick = function () {
console.log('第' + (i + 1) + '个被点击');
};
})(i)
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!