我爱编程

闭包和立即执行函数

2018-06-10  本文已影响0人  隔壁老王z

你有可能会想用全局变量,计数的时候将它加一,但是全局变量有风险,你可能会不小心改掉它,或者有时候你不希望它能被改变。

而局部变量只在函数内部有效,函数调用完后它就没了,而且全局无法使用。这时候闭包就登场了。

function plus(){
        var a = 0;
        return function(){
            return ++a
        }
 }
 var pl = plus();
 console.log(pl()); //1
 console.log(pl()); //2
 console.log(pl()); //3
 var pl2 = plus();
 console.log(pl()); //1

函数plus()定义了一个局部变量a,并返回了一个内部匿名函数,因为是内部函数,所以它可以访问其外部函数的局部变量a,并且将其加1并返回。但是由于“count()”函数已经调用完毕,我们将无法通过其他的任何办法修改"count()"中变量i的值,这就是闭包最实用的功能,就是将你想操作的变量或对象隐藏起来,只允许特定的方法才能访问。

JS高程中对闭包的定义:闭包是指有权访问另一个函数作用域中的变量的函数

函数表达式 后面 可以加() 立即调用该函数,函数声明不行 ,所以 我们想让函数声明 立即执行,就要想办法将函数声明 变成 函数表达式

var fn = function(){
    console.log(1)
}()//函数表达式后面加括号,正确
function fn(){
  console.log(1)
}()//会报错
function fn(){
  console.log(1)
}(1)//注意,不会报错,但这么写也没有意义,因为函数并不会立即执行
function(){
  console.log(1)
}()//报错,匿名函数未进行赋值操作

var fn = function(a){
  console.log(a)
}(1);//1
(function(a){
  console.log(a)
}(1));//1
(function(a){
  console.log(a)
})(1);//1
!function(a){
  console.log(a)
}(1);//1
+function(a){
  console.log(a)
}(1);//1
-function(a){
  console.log(a)
}(1);//1

因此()、!、+、-、=运算符都可以将函数声明转换成函数表达式,然后后面加()立即执行函数的代码。

立即执行函数通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏污染全局的命名空间。此时若是想访问全局对象,将全局对象以参数形式传进去即可,如jQuery代码结构:

(function(window,undefined){
    //jQuery code
})(window);

还有一个用途,就是让一个工厂方法只能被调用一次,也就是一个匿名函数,在声明的时候立即调用:

var car = function(){
  var speed = 0;
  return {
    start:function(){
      speed = 60;
    },
    getspeed:function(){
      return speed
    }
  }
}();
car.start();
console.log(car.getspeed());//60

也可以写成:

var car = (function(){
    ...
})();
或
var car = (function(){
    ...
}());

car已经不是一个函数了,它是这个匿名的工厂方法执行完返回的对象。这两个函数所需要访问的“speed”变量对外不可见 ,同时你无法再次调用这个匿名的工厂方法来创建一个相同的对象 。

上一篇下一篇

猜你喜欢

热点阅读