什么是閉包
- 閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)
- 閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中變量的函數(shù)何乎,創(chuàng)建閉包的最常見(jiàn)的方式就是在一個(gè)函數(shù)內(nèi)創(chuàng)建一個(gè)內(nèi)部函數(shù)嫩絮,通過(guò)內(nèi)部函數(shù)訪問(wèn)這個(gè)函數(shù)的局部變量,通過(guò)返回內(nèi)部函數(shù)可以突破作用鏈域
閉包的條件
- 函數(shù)嵌套
- 訪問(wèn)所在的作用域
- 在所在作用域外被調(diào)用
閉包的用途
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù).能夠讓變量常駐內(nèi)存揭绑。
-
閉包能夠封裝對(duì)象的私有屬性和方法语盈。
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')
閉包的注意點(diǎn)
- 使用閉包是的函數(shù)中的變量始終在內(nèi)存中沙合,內(nèi)存消耗很大积糯,所以不能濫用閉包绊茧,否則會(huì)造成頁(yè)面的性能問(wèn)題铝宵。解決方法是,在退出函數(shù)之前按傅,將不使用的局部變量全部刪除捉超。
- 閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值唯绍。所以拼岳,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public Method)况芒,把內(nèi)部變量當(dāng)作它的私有屬性(private value)惜纸,這時(shí)一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值绝骚。
閉包的10種表現(xiàn)形式
-
返回值
通過(guò)返回值來(lái)讀取函數(shù)內(nèi)部變量
let fn = function() { let name = 'yinyongixn' return function () { return name } } let func = fn() console.log(fnc())
-
函數(shù)賦值
將函數(shù)內(nèi)部變量賦值給外部變量
let fn2 let fn = function() { let name = 'yinyongixn' let a = function () { return name } fn2 = a } fn() console.log(fn2())
-
函數(shù)參數(shù)
將函數(shù)內(nèi)部變量作為外部函數(shù)的參數(shù)
let fn2 = function (f) { console.log(f()) } let fn = function() { let name = 'yinyongixn' let a = function () { return name } fn2(a) } fn()
-
IIFE(立即執(zhí)行函數(shù)耐版、自執(zhí)行函數(shù))
let fn2 = function (f) { console.log(f()) } ;(function() { let name = 'yinyongixn' let a = function () { return name } fn2(a) })()
-
循環(huán)賦值
在沒(méi)有l(wèi)et和const之前不存在塊級(jí)作用域,在進(jìn)行循環(huán)賦值時(shí)不能正確的賦值压汪,所以要使用立即執(zhí)行函數(shù)構(gòu)成塊級(jí)作用域來(lái)進(jìn)行正確賦值粪牲。
-
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')
-
迭代器&計(jì)數(shù)器
// 計(jì)數(shù)器 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
-
區(qū)分首次
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
-
緩存機(jī)制
// 模擬一個(gè)對(duì)象key,看該對(duì)象中是否有相同的key,如果數(shù)值相同則輸出緩存的數(shù)據(jù),否則從新計(jì)算 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對(duì)象圖片上報(bào)數(shù)據(jù)丟失
// 低版本瀏覽器在進(jìn)行數(shù)據(jù)上報(bào)會(huì)丟失30%左右的數(shù)據(jù) let report = function(src) { let imgs = [] return function(src) { let img = new Image() imgs.push(img) img.src = src } }()