什么是闭包
- 闭包就是能够读取其他函数内部变量的函数
- 闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建一个内部函数,通过内部函数访问这个函数的局部变量,通过返回内部函数可以突破作用链域
闭包的条件
- 函数嵌套
- 访问所在的作用域
- 在所在作用域外被调用
闭包的用途
闭包就是能够读取其他函数内部变量的函数.能够让变量常驻内存。
-
闭包能够封装对象的私有属性和方法。
function Person(name) { let age function setAge(n) { age = n } function getAge() { return age } return { name: name, getAge: getAge, setAge: setAge } } let p = Person('name')
闭包的注意点
- 使用闭包是的函数中的变量始终在内存中,内存消耗很大,所以不能滥用闭包,否则会造成页面的性能问题。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
闭包的10种表现形式
-
返回值
通过返回值来读取函数内部变量
let fn = function() { let name = 'yinyongixn' return function () { return name } } let func = fn() console.log(fnc())
-
函数赋值
将函数内部变量赋值给外部变量
let fn2 let fn = function() { let name = 'yinyongixn' let a = function () { return name } fn2 = a } fn() console.log(fn2())
-
函数参数
将函数内部变量作为外部函数的参数
let fn2 = function (f) { console.log(f()) } let fn = function() { let name = 'yinyongixn' let a = function () { return name } fn2(a) } fn()
-
IIFE(立即执行函数、自执行函数)
let fn2 = function (f) { console.log(f()) } ;(function() { let name = 'yinyongixn' let a = function () { return name } fn2(a) })()
-
循环赋值
在没有let和const之前不存在块级作用域,在进行循环赋值时不能正确的赋值,所以要使用立即执行函数构成块级作用域来进行正确赋值。
-
getter和setter
function Person(name) { let age function setAge(n) { age = n } function getAge() { return age } return { name: name, getAge: getAge, setAge: setAge } } let p = Person('name')
-
迭代器&计数器
// 计数器 let add = function() { let num = 0 return function() { return num++ } }() add() // 0 add() // 1 add() // 2 // 迭代器 function setUp(arr) { let i = 0 return function() { return arr[i++] } } let next = setUp(['y','y','x']) next() // y next() // y next() // y
-
区分首次
let firstLoad = function() { let list = [] return function(id) { if(list.indexOf(id) < 0) { list.push(id) return 'isFrist' }else { return 'notFrist' } } }() console.log(firstLoad(10))// isFrist console.log(firstLoad(10))// notFrist
-
缓存机制
// 模拟一个对象key,看该对象中是否有相同的key,如果数值相同则输出缓存的数据,否则从新计算 let mult = function() { let cache = {} let calculate = function() { let sum = 0 for(let i = 0;i < arguments.length;i++){ sum += i } return sum } return function() { let args = Array.prototype.join.call(arguments, ',') if(args in cache) { return cache[arges] } return cache[arges] = calculate.apply(null, arguments) } }()
-
避免img对象图片上报数据丢失
// 低版本浏览器在进行数据上报会丢失30%左右的数据 let report = function(src) { let imgs = [] return function(src) { let img = new Image() imgs.push(img) img.src = src } }()