let const
Posted zhaoyang007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了let const相关的知识,希望对你有一定的参考价值。
- 这两个是定义变量的方式,在讲清这两个之前,我们必须先讲一下前置条件,就是作用域。
- 那我们来说一下什么是作用域呢,几乎所有编程语言就是在变量中存储值,并要求能读取和修改此值,事实上,在变
量中存储值或取出值的能力给程序赋予了状态,如果没有这样的概念,一个程序虽然可以执行一些任务,但是它们将
会受到极大的限制而不会非常有趣。 - 这些变量该如何存储又该如何读取,所以程序员都设定了一些规则,比如哪些地方可以读取变量,哪些地方可以修改
变量,这个规则我们管它叫作用域。 - js层面的作用域分类
- 全局作用域
- 全局作用域的目的
希望我们在程序的任何一个地方(包括不同的文件)都可以轻易拿到我们定义的变量,那这个变量就是全局变量,
它拥有的作用域就是全局作用域。 - 什么时候定义的变量算是全局变量呢
只要在函数外部定义的变量基本上都是全局变量。 - 全局变量特别要注意的点
- 在函数内部或者代码块中没有定义的变量实际上也是全局变量,它们也是具备全局作用域的。
- 通过定义的全局变量和没有通过定义的全局变量都是挂载到全局对象window上的属性,但是通过定义的变量不
可以用delete删除,没有通过定义的全局变量可以用delete删除。
- 全局作用域的目的
- 函数作用域
- 在函数内部定义的变量就是拥有局部作用域,简称函数作用域,通常在es6之前,你说局部作用域的时候就是和全
局作用域相对的,一个是全局作用域,一个是局部作用域。这个局部作用域其实说的就是函数作用域。 - 函数作用域其实非常简单,让这个变量屏蔽在函数内部,我在这个函数内部做的事情,在函数外部你不要得倒任何
信息,它是有一个屏蔽作用的,这就是局部作用域的一个概念。 - 有的时候,我们希望这个变量屏蔽在我的函数内部,但有的时候,我希望这个函数内部的一些值是被外部所共享的,
那这个时候该怎么办呢,有两个方式:- 第一个就是使用return向外传递一个值。
- 第二个是可以利用闭包的方式向外传递这个信息。
闭包就是我并没有直接向外暴露函数内部的变量a,暴露的是这个函数,而这个函数可以拿到a,相当于通过闭包function test () { var a = 3 function test2 () { return a } return test2 }
的方式拿到了a的信息。但是你想没想过为什么我可以在test2中拿到这个变量a呢,因为test2里面的变量它依
然可以向上找,这就是作用域的本质,在当前作用域找不到的时候它向上一级作用域找。这就是把函数作用域的
作用域链。都没有的话它会找到最顶层就是window了,如果window里也没有,那这个变量就返回undefined,
作用域链就是这么一层一层的向上找的。借助函数作用域我们把作用域链又重新回顾了一遍。
- 在函数内部定义的变量就是拥有局部作用域,简称函数作用域,通常在es6之前,你说局部作用域的时候就是和全
- 块状作用域
- es6中新增加的叫块状作用域
- 可以理解为只要有花括号的地方它就是一个块,而且这个块是独立的,它可以跟外界分离开。
- 那这个块里的作用域不能再用var来定义变量了,因为在js里面有个概念,叫做变量提升。凡是用var声明的变量都
会有变量提升的概念。在这里如果用var配合我的块状作用域来做那就跟变量提升的概念相违背。 - 我们要做这个隔离块的话,就要用let和const,块状作用域加let和const配合。变量就不会有变量提升,不会变
量提升它就老老实实呆在它这个块里面。而这个块之外是不被访问到块里面的内容的。
- 动态作用域
- this到底是什么,它跟动态作用域之间有什么关系。
this是动态指向的,它不是固定指向的。它的作用域就是动态的。所以一般情况下我们管它叫做动态作用域。它是动
态的。有很多方法能够改变这个this指向。
bind的意思是说让函数动态绑定到一个对象上去,这个时候的this指向这个对象本身。由这种效果才会导致同一个window.a = 3 function test () { console.log(this.a) } test() test.bind({a: 100})()
函数却会执行出不同的结果出来。就是因为跟这个动态绑定,动态作用域有关系。- bind, call, apply
- call, apply
- 可以用来重新定义函数的执行环境,也就是this的指向。(对象拿函数的值)
- 就是将传进去的对象替换掉函数的this,以此来让这个对象拥有函数中this里面拥有的东西
- 用来做继承,使对象拥有这个函数内部用this定义的属性和方法
function ClassA () { this.a = 123 } var obj = {} console.log(obj.a) // undefined classA.call(obj) console.log(obj.a) // 123
- 特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。(函数拿对象的值)
- 就是让函数有对象中的值。
function ClassA () { console.log(this.a) } classA() // undefined classA.call({a: 123}) // 123
12注:因为更改this指向就是使对象和this相等了,所以它们之间的值就是一样的了。它们之间有同样的值,以函数中的为准。
function b () { this.a = 1 } o = { a: 2 } b.call(o) console.log(o.a) // 1
- 可以利用call和apply调用函数时的参数传递的方式来做一些有技巧性的事情。
- Math.max(1, 3, 2) // 返回一组数中的最大值
Math.max.apply(null, [1, 3, 2]) // 通过apply调用后,就可以返回一个数组中的最大值 - 将伪数组转换成数组
[].slice.call(NodeList) // 将NodeList这个伪数组转换成数组
- Math.max(1, 3, 2) // 返回一组数中的最大值
- 可以用来重新定义函数的执行环境,也就是this的指向。(对象拿函数的值)
- bind
bind()的作用与call()和apply()一样,都是可以改变函数运行时上下文,区别是call()和apply()在调用函数之后会立即执行,而bind()方法调用并改变函数运行时上下文后,返回一个新的函数,供我们需要时再调用
- call, apply
- 全局作用域
- let
- let声明的变量是拥有块级作用域的。
- 用let声明的全局变量不能通过window的属性去访问。
- var定义的变量可以重复,let声明的变量不允许重复定义。
- let声明的变量不会进行变量提升。
- const
- const具备以上let的所有特点
- const它定义的是常量。既然是常量,也就是说它不能再被修改了。
- const不允许先声明再赋值,let, var都可以。就是在声明的时候没有做初始化的动作,这个是不被允许的。
以上是关于let const的主要内容,如果未能解决你的问题,请参考以下文章