本小节主要讲解闭包,是特别重要的一块内容.希望大家能够用心学习!
作用域链的补充内容 —-> 搜索规则
如果有忘记的人,翻一下上一篇博客
注意点:如果在内层作用域中声明了和外层作用域中同名的变量,那么这个变量是不会把外层的同名变量覆盖的
搜索原则:
- 在作用域中如果访问(读取|设置)某个变量,先在当前作用域中搜索,如果找到那么就直接使用
- 如果没有找到,那么就向上一级作用域中继续搜索,找到则使用,没有找到就重复上面的过程
- 直到0级作用域链
闭包
闭 : 关闭,封闭的意思,对外界不开方的
包 : 包装起来
闭包技术
- 作用域规则 : 内层的作用域可以访问外层的的作用域,但反过来不行
- 有的时候,我们确实需要访问一个封闭空间里的数据源(外层作用域 —-> 内层作用域)
- 就是提供一种间接访问封闭空间中私有数据的方法
访问数据
- 直接返回 return
- 闭包 对直接返回的数据进行包装(函数)
- 示例代码 :
|
|
- 示例代码 : 闭包一般写法
|
|
- 示例代码 : 访问获取数据
|
|
- 示例代码 : 闭包基本写法
|
|
闭包读取数据和设置数据
- 示例代码 : 获取数据
|
|
- 示例代码 :设置数据
|
|
闭包的作用
提供了一种间接访问函数封闭空间中数据的方法
- 访问函数内部的变量只能通过指定的借口
- 对变量的修改设置操作会更加安全,可以在设置之前对数据进行校验
- 延长变量的生命周期
|
|
setTimeout和闭包的执行
setTimeout(); 只调用一次函数(延迟函数) 一次是隔两秒(至少)
每隔一定的时候就调用一次
- 参数设置 :
第一个参数:函数回调(时间到了之后执行的代码)
第二个参数:间隔时间(毫秒) 1秒 = 1000毫秒
setTimeout的问题
- 示例代码 :
|
|
解决setTimeout的问题
- 示例代码 :
|
|
div事件和闭包
- 示例代码 :
|
|
|
|
- 用闭包解决问题 :
|
|
函数的特性
- 函数本身也是对象(第一型的对象) 凡是可以使用对象的地方都可以使用函数
- 函数可以创建作用域
- 函数是可以被调用的
函数的约定和name值
- 函数声明
- 函数表达式
new 构造函数
示例代码 :
|
|
函数的回调(作为参数传递)
函数是第一型对象(因此可以使用对象的地方都可以使用函数)
- 函数可以作为函数的参数
- 函数可以作为函数的返回值
回调函数(回调),当我们把某个函数作为参数传递给另一个函数的时候,这个函数就称为回调函数。
回调函数的基本模式
- 示例代码 :
|
|
回调函数(关于this丢失的问题)
- 示例代码 :
|
|
回调函数(解决this丢失的问题)
- 示例代码 :
|
|
回调函数(兼容字符串方式)
- 示例代码 :
|
|
函数作为返回值( 计算器)
- 示例代码 :
|
|
自定义函数( 惰性函数 )
惰性函数
- 某个函数直到第一次使用的时候才被正确的定义,并且其具有向后惰性,执行更少的工作。
应用场景
- 函数有一些初始化的准备工作要做,且只需要执行一次的情况。
特点
- 能够更新自己(函数)的实现。
缺点:
- 当重新定义自身的时候,已经添加到原始函数的任何属性都会丢失。
- 如果函数被赋值给了其他的变量或者是对象方法,那么在使用变量或者是对象方法调用时仍然会执行旧的函数体。
- 示例代码 :
|
|
惰性定义函数存在的问题
- 添加属性
- 把函数赋值给新的变量
- 以对象的方法调用函数
- 示例代码 :
|
|
即时函数
在函数定义之后立即执行该函数。
即时函数模式的组成:
- 使用函数表达式来定义函数(匿名函数,注意不能使用函数声明方式)
- 在函数表达式末尾添加一组(),表示立即执行当前函数。
- 将整个函数包装在()中,有两种方式
即时函数的作用
- 用来将所有的代码包装到当前的作用域中,并且不会将任何的变量泄露到全局作用域中。
- js中没有代码块作用域,而函数是js中唯一可以创建作用域的。
- 即时函数就是利用了函数创建作用域这一点,来实现对一些需要封装且不允许外部访问的操作。
即时函数的优点
- 封装在一起执行的代码,且不会产生全局变量,在即时函数内部定义的所有变量都仅仅只是该函数的局部变量,不会造成全局变量污染问题。
- 具有更好的封装性,外部无法访问到该函数内部的数据。
- 示例代码 : 即时函数两种写法
|
|
- 示例代码 : 即时函数可以接受参数并提供返回值
|
|
即时函数和闭包
相同点:他们都是函数的一种特殊形态,并且可以共存。而且闭包配合即时函数“效果更佳”。
不同点:即时函数是定义一个函数,并立即执行。它只能被使用一次,相当于“阅后即焚”。闭包是指一个函数与它捕获的外部变量的合体,按照MDN的说法,闭包就像一个对象—一个具有一个方法(行为)和一个或多个私有字段(状态)的对象。从这个角度看,闭包是符合面向对象的封装思想的。
即时对象初始化
结构特征
- 提供一个对象,在该对象内部提供一个init初始化方法,使用()把对象包装起来(让字面量变成表达式)
- 然后随即调用init方法,完成初始化操作。
基本结构
({}).init();
模式优点
- 在执行一次性的初始化任务时保护全局的命名空间。
- 示例代码 :
|
|