目录

  • var的特点
    • 1.作用域是全局作用域,没有块级作用域的概念
    • 2.存在变量提升
  • let的特点
    • 1.let声明的变量拥有块级作用域,let声明仍然保留了提升特性
    • 2.let声明的全局变量不是全局对象的属性,不可以通过window.属性名的方式访问这些变量
    • 3.var和let定义的变量在同一个作用域中不能重复声明
    • 4.var、let都支持解构特性
  • const的特点
    • 1.声明时就要进行赋值
    • 2.一般常量使用大写(潜规则)
    • 3.常量的值不能修改
    • 4.块级作用域
    • 5.对于数组和对象的元素修改,不算做对常量的修改
    • 6.不能重复声明

var的特点

1.作用域是全局作用域,没有块级作用域的概念

使用var声明的变量,无论是在全局还是函数内部,生成的变量都会是全局变量,作用域是全局作用域,无论在哪个代码块中都可以直接访问到,此时我们可能就会想是不是无论在哪里都能够修改var声明的变量的值呢?让我们看一下下面的代码:

var a = 10;
function b (value) {value = 2;console.log(value);
}
b(a);//2
console.log(a);//10
function c () {console.log(a);a = 2;console.log(a);
}
c();// 10 2
console.log(a);//2

从代码运行的结果可以看出,var声明的变量作为参数传入函数中时,在函数里面修改参数的值,此时函数外部对应的变量的值不变;为什么会出现这种结果呢?
因为当var声明的变量a作为参数传入函数b时,进行的是值的传递,即把a的值10赋值给了函数b作用域中的变量value(相当于克隆),这是a与value是没有联系的,在函数中无论怎样修改value的值都不会对a产生影响;
而当变量a没有作为参数传入函数时,执行函数c时,编译器会从函数c的执行上下文中查找变量a,因为在函数执行上下文中没有找到,就会往全局执行上下文查找,从而找到全局作用域下的a,此时如果在函数中修改a的值编译器会找到全局作用域下的a进行修改。
下面我们再看另一种情况;当参数是对象类型时,又会是什么结果?

var a = [10, 2];
function b (value) {value[0] = 3;console.log(value);
}
b(a);//[3,2]
console.log(a);//[3,2]function c () {console.log(a);a[0] = 2;console.log(a);
}
c();//[2,2]
console.log(a);//[2,2]

从上面的结果可以看出,当参数为对象类型时,将对象作为参数传入函数中进行修改和直接在函数中进行修改结果是一样的;这是因为在对象变量a对应的内存中存储的是指向数组[10,2]的指针,也就是数组[10,2]对象的地址,对象数据类型(Object、Function、Array)是存储在堆空间中的,而普通数据类型在栈空间中,对象a作为参数时,就将地址值赋值给了value,此时函数中的value与a都指向了数组[10,2];无论对a还是value进行修改最终实际都是在修改数组。

2.存在变量提升

什么是变量提升?

a();//a is not a function
fun();//hello
fun2();//fun2 is not defined
var a = function () {console.log('hello');
}
function fun () {console.log('hello');
}console.log(b);//undefined
console.log(d);//d is not defined
var b = 'hello';

变量的提升就是编译器在执行代码时,会先创建相应的执行上下文(全局执行上下文、函数执行上下文),在执行上下文中保存了函数、变量的声明,然后编译器才开始从上至下执行每一条语句;
在执行第一条语句时,因为变量提升的特性,在全局执行上下文中存在变量a的声明,但此时还没有执行后面的赋值语句将函数赋值给变量a,所以编译器认为a是个变量,报出错误a is not a function;而在执行到打印b变量时,同理,因为变量提升,控制台显示的结果为undefined,意思就是变量b已经声明了,并初始化为undefined;之后的打印d变量,因为整段代码中都没有声明d变量,也就不存在变量提升,所以报出错误d is not defined,意思是在代码中没有声明变量d。
在执行代码中的第二条语句时,在全局执行山下文中已经有了函数的声明(称为函数提升),结果为hello;而在执行第三条语句时,因为整段代码中都没有声明函数fun2(),也就不存在函数提升,所以报出错误fun2 is not defined。

let的特点

1.let声明的变量拥有块级作用域,let声明仍然保留了提升特性

var a = 2
let b = 3
function fun() {console.log(++b)let c = 'dk'
}
fun()
console.log(b) //4
console.log(c) //c is not defined

在ES5中有全局、函数、eval(在严格模式下)三种作用域;let是在ES6中引入的新语法,主要是为了解决var的缺点:没有块级作用域的;这可以说是JavaScript的一个缺陷,由于var没有块级作用域的概念导致无论在函数内部还是外部定义的变量都会变成全局变量,造成全局环境的污染;有时我们不希望在函数的外部去访问函数内部定义的变量,显然var不能满足我们的需求,这时使用let就能完美的解决我们的问题。
说到let有没有变量提升,这是个争议比较大的问题,笔者认为let保留了提升的特性,但不会盲目的提升。

console.log(a);//undefined
console.log(b);//Cannot access 'b' before initialization
var a = 2;
let b = 3;

从上面代码的结果我们就可以发现问题,如果说let声明的变量不存在变量提升的话,第二条语句执行的结果应该是 b is not defined,而不是上面的结果,为什么会是这样呢?因为let保留了部分的提升特性,变量存在声明、初始化和赋值三大过程,var声明的变量声明、初始化都提升了,也就是编译器开始执行代码时,首先在执行上下文中保存了变量的声明,同时将变量初始化为undefined;而使用let声明的变量则只是进行了声明的提升,在执行上下文中保存了变量的声明,但并没有初始化,所以就会出现上面的结果Cannot access ‘b’ before initialization。
想要深入了解let变量提升?

2.let声明的全局变量不是全局对象的属性,不可以通过window.属性名的方式访问这些变量

<script>var a = 2let b = 3console.log(window.a, window.b);//2 undefined
</script>

通过上面的代码可以发现使用var定义的变量会成为window全局对象的属性,有人可能会有疑惑:上面的代码中打印window.b结果出现undefined,那是不是说明window全局对象中存在变量b,b被赋值为了undefined?其实这是因为:JS中如果对象不存在属性,那么访问这个不存在的属性时,编译器不会报错,而是访问的结果为undefined;由于报错会导致程序停止执行后面的代码,有时我们希望在访问一个变量时,变量不存在的情况下代码也不要报错,就可以考虑利用编译器的这个特性,通过对象属性去访问变量,比如:我们访问上面的变量a时可以使用window.a来代替。

3.var和let定义的变量在同一个作用域中不能重复声明

var a = 're'var a = 'hello'//Identifier 'a' has already been declared
let h = 'hello'
let h = 'world' //报错 Identifier 'h' has already been declared
var b = 'we'
let c = 'wo'
function fun() {var b = 1let c = 2console.log(b, c)}
fun()//1 2
console.log(b, c)//we wo

通过代码可以知道var和let定义的变量在相同作用域下都不可以重复声明;上面的代码中变量b、c在全局作用域和函数作用域中进行了声明,此时的重复声明不会报错。

4.var、let都支持解构特性

解构是ES6新增的一种获取对象中的属性值和数组中相应元素值的方法;相比于传统的方法它更加简洁,访问属性的方法也更加清晰;解构分为对象解构和数组解构;下面用代码演示一下用法

//数组解构
const F4 = ['小沈阳', '刘能', '赵四', '宋小宝'];
let [xiao, liu, zhao, song] = F4;
console.log(xiao, liu, zhao, song);//小沈阳 刘能 赵四 宋小宝
let [we] = F4;
console.log(we);//小沈阳
//对象解构
const zha = {name: 'zhaobenshan',age: '不详',xiaopin: function () {console.log('我可以演小品');}
}
let { a } = zha;
console.log(a);//undefined
let { name } = zha;
console.log(name);//zhaobenshan

对于对象的解构通过相应的属性名将属性值赋值给变量名与属性名相同的变量;对于数组的解构通过变量声明时所在的下标将数组中的值赋值给相应下标的变量。

const的特点

1.声明时就要进行赋值

const A;//Missing initializer in const declaration

2.一般常量使用大写(潜规则)

3.常量的值不能修改

const SCHOOL = 'zhku123';
SCHOOL = 'zl';//Assignment to constant variable

4.块级作用域

{const PLAYER = 'UZI';
}
console.log(PLAYER);//PLAYER is not defined

5.对于数组和对象的元素修改,不算做对常量的修改

const TEAM = ['UZI', 'MXLG', 'Ming', 'Letme']
TEAM.push('Meiko')
console.log(TEAM)//['UZI', 'MXLG', 'Ming', 'Letme', 'Meiko']

6.不能重复声明

const A = 'ko'
const A = 12 //Identifier 'A' has already been declared

JS/ES6-var、let、const用法与区别相关推荐

  1. Js中var,let,const的区别

    一:区别: 1.var声明的变量属于函数作用域,而let和const声明的变量属于块级作用域:(js作用域在上篇文章) 2.var声明的变量存在变量提升,而let和const没有 3.var声明的变量 ...

  2. JS Statements var / let / const

    关键字 范围 变量提升 可以重新分配 可以重新定义 var 全局.局部 Yes Yes Yes let 局部 No Yes No const 局部 No No No 能用const的情况尽量使用con ...

  3. js中 var a 和 a 的区别

    先看一段代码: var name = 'Tom'; function say() {if (name == undefined) {var name = 'Jack'console.log('good ...

  4. js中slice、splice用法与区别

    1.slice(start,end)(参数可选) slice() 方法返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象.原始数组不会被修改. var a = ['a', 'b ...

  5. js定时器setTimeout和setInterval用法及区别,清除定时器的使用

    setTimeout和setInterval使用方法 定时器两个参数,第一个是执行代码,第二个是执行时间.执行时间自己随便设置,执行代码有以下几种方式传入: 1.匿名函数形式传入 setTimeout ...

  6. JS中splice、slice用法及区别

    splice 向数组中添加或删除元素,然后返回含有被删除元素的数组 注意:这种方法会改变原始数组 语法 array.splice(index,howmany,item1,-,itemX) 参数 ind ...

  7. 前端开发:JS中let、var和const的区别详解

    前言 前端开发过程中,JS声明变量的关键字想必开发者都不陌生,而且使用的频率在前端开发过程中也是数一数二的.JS中声明变量的关键字有三个let.var和const,但是三者的使用对比和区别也是非常重要 ...

  8. 微信小程序--var、let、const的用法及区别

    前言 初学小程序时,在js中经常会申明变量,但是有时用var,有时用let,有时又用const.开始也没有仔细去研究区别,反正一律就用var(现在看来,以前的自己好懒) var 概念:var申明的变量 ...

  9. ES6学习(var,let,const区别)

    本人写这个专题的博客是为了总结一下自己学习,使用还有刷题时学到的ES6知识点,并做以归纳. var,let,const 三个属性都可以声明变量. 作用域 var  重新赋值,重新定义变量,可以重复声明 ...

最新文章

  1. 幼儿园语言活动包括哪几类_幼儿园小班语言游戏教案你问我答对话活动教学【幼儿教师教案】...
  2. px,em, rem的区别,在项目中怎么使用rem.
  3. Release编译模式下,事件是否会引起内存泄漏问题初步研究
  4. C++ 基于凸包的Delaunay三角网生成算法
  5. C/C++ union
  6. C# Winform SplitContainer组件创建侧边菜单
  7. SharePoint开发环境配置
  8. 《暗时间》读书笔记及读后感
  9. 伺服电机的工作原理是什么
  10. 防腐投加器需要加盐吗_什么情况下需要往鱼缸里加盐?盐有什么作用?
  11. 用C#实现一个zip解压功能,无需引入dll(可直接放到Unity中使用)
  12. 只要你足够好——写给理想受挫的人们
  13. 【蓝桥杯经典数学题】杨辉三角形
  14. Android 11 Bubble通知的原理
  15. 【公众号技能+】添加白名单,允许其他公众号转载文章
  16. Linux中修改用户UID和组GID的方法
  17. 在Maven中出现Could not find artifact ...:pom:0.0.1-SNAPSHOT and ‘parent.relativePath‘的错误怎么解决?
  18. 音痴测试软件,测试你是一个五音不全的音痴吗
  19. C#字符串格式输入不正确怎么办?
  20. Hadoop3.2.0 Hadoop 机架感知

热门文章

  1. 2021-09-29 计算BMI值(国际上常用的衡量人体胖瘦程度的一个标准)(要保留多少位有效数字可以用python内置的 round 函数)
  2. C语言--已知三边求三角形面积
  3. 【PCA、LDA降维,及模型评估(SE,SP,AUC)】
  4. zepto和jquery
  5. 计算机网络知识面试常考
  6. 【AI视野·今日CV 计算机视觉论文速览 第159期】Tue, 24 Sep 2019
  7. dnn解读_论文学习+解读1--受优化算法启发的DNN网络设计
  8. 【BZOJ3442】学习小组 费用流
  9. 一文教你快速搞懂速度曲线规划之S形曲线(超详细+图文+推导+附件代码)
  10. netkeeper客户端_星空极速下载-NetKeeper官方版下载[电脑版]-华军软件园