JS学习笔记——闭包

1. 什么是闭包

MDN定义:Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions 'remember' the environment in which they were created.

You Don't Know JS: Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.

我所理解的闭包就是,即使外部函数已经运行完毕,内部函数仍能访问外部函数的作用域中的变量。

抓重点: 函数, 作用域。

2. 闭包的运行机制

2.1 词法作用域查找规则

在闭包的使用中,为什么我们能够通过闭包访问外部函数的作用域中的变量?其一,词法作用域的查找规则是“冒泡”的,即向外层一层层查找,直到全局作用域,所以能够访问外部函数的作用域。其二,函数的作用域是定义时所在的作用域,而不是运行时的作用域。

function foo() {
  var a = 1;
  
  function bar() {
      console.log(a);
  }
 
 return bar;
}

var a = 2;
var baz = foo();
baz(); //1

在上面的代码中,由于bar定义在foo的内部,因此能够向外“冒泡”访问foo的作用域。当运行baz时,a的值为1而不是2,也说明了函数的作用域是定义时的作用域,是静态的。

2.2 垃圾回收 + 引用

当函数执行完毕后,引擎的垃圾回收机制会释放不再使用的内存空间。因此,当外部函数执行完毕时,外部函数的内部作用域理应是该被销毁的。然而,由于闭包存在对外部函数作用域的引用,因此此作用域仍然存在,所以内部函数仍能在外部函数执行结束之后访问外部函数定义的变量,此之为“记住”

3. 闭包的应用场景

3.1 私有变量 + 模块

需求:只能通过函数提供的方法访问函数内部的变量——隐藏。只能内部访问——私有。

function bookInfo() {
  var book = {
        name: "You Don't know JS",
      price: 66
    };
        
    function getPrice() {
        console.log(book.price);
    };
    
    function getName() {
        console.log(book.name);
    };
    
    function setPrice(price) {
        book.price = price;
    };
    
    return {
        getPrice,
      getName,
      setPrice
    };
  };

  var book = bookInfo();
  
  book.getPrice(); //66
  book.getName(); //"You Don't know JS"
  book.setPrice(100);
  book.getPrice(); //100

在以上的代码中,bookInfo通过返回一个对象,该对象的值是对内部函数的引用,而不是对变量的引用。因此,实现了函数内部变量是隐藏的(只能通过返回的对象方法访问)且私有的(只有函数内部才能访问)。

在模块中,返回的变量就被称为模块的公共API,模块内部的变量只能通过这些方法去使用。

3.2 偏函数应用

需求:函数需要先接受一些参数,随后再接受另一些参数的时候。
比如,当我计算商品的总价格时,我想先设定商品的单价,随后根据购买数量算出总的商品价格。

  function partialApply(fn, ...fixedArgs) {
    return function (...remainingArgs) {
        return fn.apply(this, fixedArgs.concat(remainingArgs));
    }
  }
  
  function calTotalPrices(price, count) {
      console.log(price * count);
  }
  
  var pay = partialApply(calPrice, 10);
  
  pay(5);

在上面的代码中,pay就是在partialApply的外部访问了partialApply的内部变量(函数参数)。

4. 为什么闭包很重要?

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值