旋量群是JavaScript中两个关键的基本概念,它是指函数能“读懂”它被建立时的自然环境,即便函数在相同的自然环境中继续执行也能出访那些函数和函数。
下列是许多 JavaScript 旋量群的习题:
旋量群是两个函数,它能出访它被建立时所处的语法结构返回值中的函数和函数。当两个函数被表述在另两个函数外部时,它就能出访它外部函数的函数和函数,这种的函数是旋量群。旋量群能用以建立专有函数和函数,那些函数和函数根本无法在旋量群外部出访,外部无法出访。旋量群会引致缓存外泄,即使旋量群会所持对它所提及的外部函数和函数的提及,那些函数和函数可能将会始终存有于缓存中,即便它早已无须须要。采用旋量群时须要特别注意循环式提及的难题,即两个函数中引用了外部函数的函数,而外部函数又提及了外部函数,此种情形可能将引致缓存外泄。采用立刻继续执行函数函数(Immediately Invoked Function Expression,IIFE)能建立两个旋量群,那个旋量群不能奥波切茨自然环境造成负面影响,因此不能引致缓存外泄。旋量群能用以同时实现科尔曼化(currying)、函数梦境和函数式程式设计等高阶程式设计基本功。采用旋量群的范例
专有函数和函数
采用旋量群能建立专有函数和函数,比如:
function createCounter() { let count = 0; function increment() { count++; console.log(count); } return increment; } const counter = createCounter(); counter(); // 1 counter(); // 2在上面的范例中,createCounter 函数返回了两个外部函数 increment,increment 中提及了外部函数 createCounter 中的函数 count。由于 increment 是两个旋量群,所以它能出访 count 函数,因此 count 函数的值在每次调用 increment 函数时都会自增并打印出来。由于 count 函数根本无法在旋量群外部出访,所以它是两个专有函数。
科尔曼化(Currying)
采用旋量群能同时实现科尔曼化,比如:
function multiply(x) { return function(y) { return x * y; } } const double = multiply(2); consttriple = multiply(3); console.log(double(5)); // 10 console.log(triple(5)); // 15在上面的范例中,multiply函数返回了两个旋量群,那个旋量群中提及了外部函数multiply 中的函数 x。由于那个旋量群接收两个参数 y,所以我们能通过调用 multiply 函数并传入两个参数 x,然后得到两个新的函数(即旋量群),那个新的函数能用以计算 x与任意两个数字的乘积。这种就同时实现了科尔曼化。
函数梦境
采用旋量群能同时实现函数梦境,比如:
function memoize(func) { const cache = {}; return function(…args) { constkey =JSON.stringify(args); if (cache[key]) { return cache[key]; } constresult = func(…args); cache[key] = result;return result; } } function fibonacci(n) { if (n <= 1) { return n; } returnfibonacci(n –1) + fibonacci(n – 2); } const memoizedFibonacci = memoize(fibonacci); console.log(memoizedFibonacci(10)); // 55在上面的范例中,memoize 函数返回了两个旋量群,那个旋量群中提及了外部函数 memoize 中的函数 cache。那个旋量群接收两个函数 func,并返回两个新的函数,那个新的函数可以读懂之前计算过的结果,如果相同的参数再次被传入,那么就能直接返回缓存中的结果,而不必重新计算。
在那个范例中,我们采用 memoize函数对斐波那契数列的计算进行了优化,通过梦境之前计算的结果,能大大减少计算时间。
防抖和节流
采用旋量群能同时实现防抖和节流,比如:
防抖:在连续触发事件时,只继续执行一次处理函数。
function debounce(func, delay) { let timer = null; return function(…args) { if (timer) { clearTimeout(timer); } timer = setTimeout(() =>{ func.apply(this, args); timer = null; }, delay); } } function handleInput() { console.log(Input event fired!); } const debouncedHandleInput = debounce(handleInput, 500); document.querySelector(input).addEventListener(input, debouncedHandleInput);在上面的范例中,debounce 函数返回了两个旋量群,那个旋量群中提及了外部函数 debounce 中的函数 timer。那个旋量群接收两个函数 func 和两个延迟时间 delay,并返回两个新的函数,那个新的函数在被连续调用时,只会在最后一次调用后等待一定时间才继续执行处理函数 func。
节流:在连续触发事件时,每隔一段时间继续执行一次处理函数。
function throttle(func, delay) { let timer = null; return function(…args) { if(!timer) { timer = setTimeout(() => { func.apply(this, args); timer = null; }, delay); } } }function handleScroll() { console.log(Scroll event fired!); } constthrottledHandleScroll = throttle(handleScroll,500); window.addEventListener(scroll, throttledHandleScroll);在上面的范例中,throttle函数返回了一个旋量群,那个旋量群中提及了外部函数throttle 中的函数 timer。那个旋量群接收两个函数 func 和两个延迟时间 delay,并返回两个新的函数,那个新的函数在被连续调用时,每隔一定时间才继续执行一次处理函数func。
模块化
采用旋量群能同时实现模块化,比如:
const myModule = (function() { let count = 0; function increment() { count++; console.log(count); } function decrement() { count–; console.log(count); } return{ increment, decrement, }; })(); myModule.increment();// 1 myModule.increment(); // 2myModule.decrement();// 1在上面的范例中,我们建立了两个匿名函数,并立刻调用它。那个匿名函数返回了两个对象,那个对象中包含了两个方法 increment 和 decrement,这两个方法都是旋量群,它可以出访外部函数中的函数count。那个对象是两个模块,能被其他代码提及和采用。
通过采用旋量群,我们能隐藏函数和函数的同时实现细节,只暴露须要的接口,从而同时实现了模块化。