前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4 个关于JavaScript 中闭包的有用技巧

4 个关于JavaScript 中闭包的有用技巧

作者头像
前端老道
发布2023-10-09 15:49:40
1580
发布2023-10-09 15:49:40
举报
文章被收录于专栏:Vue开发社区

英文 | https://javascript.plainenglish.io/4-tricks-and-tips-about-closure-in-javascript-you-should-know-a7fe6aeaa767

什么是闭包?

根据 MDN:“闭包是捆绑在一起(封闭)的函数及其周围状态(词法环境)的引用的组合。换句话说,闭包使您可以从内部函数访问外部函数的作用域。在 JavaScript 中,每次创建函数时都会创建闭包。”

例如

代码语言:javascript
复制
const getShowName = () => {
  const name = "fatfish" // name is a local variable created by getShowName

  return () => {
    console.log(name) // use variable declared in the parent function
  }
}

const showName = getShowName()

showName() // fatfish

作为前端开发工程师,我们在很多场景中都会用到它,它的功能确实很强大。

1. 解决循环中的问题

代码语言:javascript
复制
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // What will i print out?
  }, 1000 * i)
}

我们怎样才能让它打印0、1、2呢?

是的,你可以使用闭包来解决这个问题。它很快就会打印出 0、1 和 2。

代码语言:javascript
复制
for (var i = 0; i < 3; i++) {
  ((n) => {
    setTimeout(() => {
      console.log(n) // What will i print out?
    }, 1000 * n)
  })(i)
}

当然,我们还有另一种更简单的方法,只需将var替换为let即可解决这个问题。

代码语言:javascript
复制
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i) // What will i print out?
  }, 1000 * i)
}

2.记忆功能

利用闭包的特性,我们可以减少计算量,提高我们编写的程序的性能。

代码语言:javascript
复制
const memoize = (callback) => {
  const cache = new Map()

  return function (n) {
    if (cache.has(n)) { // When it already exists in the cache, the result will be returned directly, we don't need to calculate it again
      return cache.get(n)
    } else {
      const res = callback.call(this, n)
      cache.set(n, res) // After the first calculation, the result will be cached
      return res
    }
  }
}
const fibonacci = memoize(function fib (n) {
  if (n === 1) {
    return 1
  }
  if (n === 2 || n === 3) {
    return 2
  }
  return fib(n - 1) + fib(n - 2)
})

console.log(fibonacci(1)) // 1
console.log(fibonacci(10)) // 68
console.log(fibonacci(10)) // 68 Read from cache instead of computing again

3. 封装私有变量和属性

很早以前,我们经常通过闭包来实现对私有变量的保护。

我们只能通过getName和setName来获取和设置_name的值。

这样我们就可以有效防止_name被恶意修改。

代码语言:javascript
复制
const createName = (name) => {
  let _name = name

  return {
    getName () {
      return _name
    },
    setName (name) {
      _name = name
    }
  }
}
const p = createName('fatfish')
p.getName() // fatfish
p.setName('medium')
p.getName() // medium

4.函数柯里化

作为一名前端开发工程师,我相信你已经了解了什么是函数柯里化。让我们尝试使用闭包来实现它。

代码语言:javascript
复制
const curry = (callback, ...args) => {
  return function (...innerArgs) {
    innerArgs = args.concat(innerArgs)

    if (innerArgs.length >= callback.length) {
      return callback.apply(this, innerArgs)
    } else {
      return curry(callback, innerArgs)
    }
  }
}

const add = curry((a, b, c) => {
  return a + b + c
}, 1)
console.log(add(2, 3)) // 6

太好了,我们做到了,那你还知道闭包的其他用途吗?如果你知道的话,请在留言区跟我一起来分享它,我们一起学习进步。

最后,感谢你的阅读,祝编程愉快!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端开发社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档