闭包

闭包是指有权访问另一个函数作用域中的变量的函数(红皮书);

闭包是函数和声明该函数的词法环境的组合(MDN)。

当函数可以记住并访问所在的词法作用域时,就产生了闭包(你不知道的js)。

以上是翻阅的三个答案,其中都提到了作用域和访问函数作用域,这与红皮书的执行环境、作用域链有关,我有整理在随笔中。

function foo () {

  var a = 2;

  function bar () {

    console.log(a);

  }

  return bar;

}

var baz = foo();

baz(); //2

上面的例子向我们展示了闭包的效果。bar()的词法作用域能够访问foo()的内部作用域,baz执行实际上只是通过不同的标识符调用了bar();

通常foo执行完后,foo的内部作用域会被销毁,但是闭包阻止了这件事情的发生,因为bar() 一直在使用它,使得该作用域能够一直存活,以供bar() 在之后任何时间进行引用。

bar()依然持有对该作用域的引用,而这个引用就叫作闭包。

例1:

function foo () {

  var a = 2;

  function baz () {

    console.log(a);

  }

  bar(baz);

}

function bar(fn) {

  fn();

}

foo();

bar();//2

 

例2:

var fn;

function foo () {

  var a = 2;

  function baz () {

    console.log(a);

  }

  fn = baz;

}

function bar(fn) {

  fn();

}

foo();

bar();//2

 

闭包的身影

无论何时何地,如果将函数当作第一级的值类型并到处传递,就会有闭包在这些函数中应用。在定时器、事件监听、Ajax请求、跨窗口通信、web Workers或者任何其他的异步(或者同步)任务中只要使用了回调函数,实际上就是在使用闭包。

循环与闭包

 

for ( var i = 0; i<5; i++ ){

  (function(){

    setTimeout(function timer() {

      console.log(i);

    },1000);

  })();

}

// 5 ....

for ( var i = 0; i<5; i++ ){

  (function(){

    var j = i;

    setTimeout(function timer() {

      console.log(j);

    },1000);

  })();

}

// 0 1 2 3 4

循环1虽然把作用域封闭起来,但作用域是空的,所以并不能达到想要的目标,可见仅仅封闭是不够的,只有包含一点实际的变量才能为我们所用。

 

模块

function a () {

  function b () {
  

  }

  function c () {
  

  }

  return {

    b: b,

    c: c

  }

}

var d = a();

d.b();

d.c();

这个模式在JS中被称为模块。最常见的实现模块模式的方法通常被称为模块暴露,展示的是其变体。

现代模块机制

var Modules = (function Manager() {

  var modules = {};

  function define (name, deps, impl) {

    for(var i = 0; i<deps.length; i++) {

      deps[i] = modules[deps[i]];

    }

    modules[name] = impl.apply( impl, deps );

  }

  function get(name) {

    return modules[name];

  }

  return {

    define: define,

    get: get

  }

})();

 

Modules.define( "bar", [], function(){

  funciton hello(who) {

    return "Hello " + who;

  }

  return {

    hello: hello

  };

});

Modules.define("foo", ["bar"], function(bar){

  var hungry = 'hippo';

  function awesome() {

    console.log( bar.hello( hungry ).toUpperCase() );

  }

  return {

    awesome: awesome

  }

});

var bar = Modules.get( "bar" );

var foo = Modules.get( "foo" );

console.log( bar.hello('world') );

foo.awesome();// Hello hippo

posted @ 2018-06-30 11:47  一纸折寒  阅读(165)  评论(0编辑  收藏  举报