这是我参与「第四届青训营 」笔记创作活动的第 5天
作用域和自由变量
作用域:
代表了一个变量合法的使用范围
-
全局作用域:
一个被全局定义的变量,没有受到任何函数的约束,在全局都可以使用。
-
函数作用域:
在一个函数中定义的变量,只能在当前函数使用。
-
块级作用域:
这里的块:是指 if, for, while 等后面有个大括号。
在一个块中定义的变量,只能在当前块使用。
-
自由变量:
代表一个变量在当前作用域没有定义,但被使用了。
这时候,会向上级作用域,一层一层的查找,直至找到。
如果到全局作用域都没找到,则报错 xx is not define.
闭包
有两种表现:
1. 函数作为返回值
100
函数定义在create作用域, a = 100 也在create作用域
console.log(a),变量a先去定义的地方寻找。fn函数作用域里面没有,
因此是个自由变量,往上层查找,找到a = 100.
2. 函数作为参数被传递 :
100
函数定义在全局作用域
a = 100 也在全局作用域
console.log(a),变量a先去定义的地方寻找。fn函数作用域里面没有,
因此是个自由变量,往上层查找,找到 a = 100.
总结: 闭包有两种形式,1: 函数作为返回值。2: 函数作为参数被传递。
形成的原因是,函数中使用了自由变量。
闭包(或者说 所有变量的查找)中。自由变量的查找,是在函数定义的地方开始,向上级作用域查找,不是在执行地方!!!!
闭包常常由于,用于隐藏数据,如做一个简单的 cache 工具。这样缓存中 data 的就只能够通过提供的 set, get 方法操作进行数据的获取和写入。外界没有办法直接更改缓存中 data
this
this取什么值,是在函数执行时确定的!!!不是在函数定义时确定的。
应用场景:
(1)作为普通函数被调用
Window
(2)使用 call apply bind去调用
call, bind(和call不同在于,返回一个函数执行)来改变this的指向
(3)作为对象方法被调用
代表当前对象
!!! 注意️ set Timeout里面的this,指向一定是window。
箭头函数里面的this,取它上级作用域的值。
(4)在class方法中被调用
代表正在创建的那个实例。
(5)箭头函数
箭头函数里面的this,取它上级作用域的值。
总结:
-
当成普通函数被调用:window
-
使用 call apply bind时: this绑定传入的对象
-
a.call(b,arg1,arg2..) apply(obj,args) bind时
-
在对象的方法中调用:对象本身
-
在class的方法中调用:当前实例本身
-
setTimeout方法里面:window
-
箭头函数:和上级作用域里this一致
实际开发中闭包的应用场景
举例说明:
用于隐藏数据,如做一个简单的cache工具。
这样data的值就只能够通过set, get方法操作,外界没有办法直接更改。
(只看script)
Js 创建10个 <a> 标签,点击的时候弹出对应的序号
// let i, a
这样会出现alert的一直是10。
因为代码执行很快就会执行完,遍历10遍,创建a标签,绑定事件。这个事件在此期间还没有执行。
这个事件什么时候click什么时候才执行,所以如果i是个全局的变量,执行的时候早就已经是10了。
下面这样更改, i存储在块作用域,每次for循环都会形成一个新的块。i 就会在块级作用域找到。
参考链接: