一個函數包裹另外一個函數,被包裹的函數成爲閉包函數,外部函數爲閉包函數提供了一個閉包做用域???segmentfault
function outer() { let bar = 'foo' function inner() { debugger console.log(bar) // 閉包函數用到了外部函數的變量bar } return inner } let foo = outer() // 執行外部函數返回內部函數 foo() // 執行內部函數
因此,閉包函數必需要被外部變量持有???數組
function outer() { let bar = 'foo' function inner() { debugger console.log(bar) } inner() // 直接在外部函數中執行了閉包函數inner } outer()
因此,被包裹的閉包函數是否被外部變量持有並非造成閉包的條件閉包
function outer() { let bar = 'foo' function inner() { console.log(bar) } function hello() { // hello沒有使用外部outer函數的變量 debugger } hello() } outer()
依舊造成了閉包,由於閉包做用域是內部全部閉包函數共享的,只要有一個內部函數使用到了外部函數的變量便可造成閉包app
因此造成閉包的條件: 存在內部函數使用外部函數中定義的變量
見具體文章https://segmentfault.com/a/11...函數
let li = document.querySelectorAll('li'); for(var i = 0; i < li.length; i++) { (function(i){ li[i].onclick = function() { alert(i); } })(i) }
概念:把接受多個參數的函數變換成接受單一參數的函數,而且返回接受餘下的參數並且返回結果的新函數的技術ui
function currying(fn,...res1) { return function(...res2) { return fn.apply(null, res1.concat(res2)) } } function sayHello(name, age, fruit) { console.log(console.log(`我叫 ${name},我 ${age} 歲了, 我喜歡吃 ${fruit}`)) } const curryingShowMsg1 = currying(sayHello, '小明') curryingShowMsg1(22, '蘋果') // 我叫 小明,我 22 歲了, 我喜歡吃 蘋果
高級柯里化函數this
function curryingHelper(fn, len) { const length = len || fn.length // 第一遍運行length是函數fn一共須要的參數個數,之後是剩餘所須要的參數個數 return function(...rest) { return rest.length >= length // 檢查是否傳入了fn所需足夠的參數 ? fn.apply(this, rest) : curryingHelper(currying.apply(this, [fn].concat(rest)), length - rest.length) // 在通用currying函數基礎上 } } function sayHello(name, age, fruit) { console.log(`我叫 ${name},我 ${age} 歲了, 我喜歡吃 ${fruit}`) } const betterShowMsg = curryingHelper(sayHello) betterShowMsg('小衰', 20, '西瓜') // 我叫 小衰,我 20 歲了, 我喜歡吃 西瓜 betterShowMsg('小豬')(25, '南瓜') // 我叫 小豬,我 25 歲了, 我喜歡吃 南瓜 betterShowMsg('小明', 22)('倭瓜') // 我叫 小明,我 22 歲了, 我喜歡吃 倭瓜 betterShowMsg('小拽')(28)('冬瓜') // 我叫 小拽,我 28 歲了, 我喜歡吃 冬瓜
可能會引發內存泄露,具體見https://segmentfault.com/a/11...spa