闭包和立即执行函数
2018-06-10 本文已影响0人
隔壁老王z
- 闭包:先来看一个题目:实现一个函数,每次调用自增1
你有可能会想用全局变量,计数的时候将它加一,但是全局变量有风险,你可能会不小心改掉它,或者有时候你不希望它能被改变。
而局部变量只在函数内部有效,函数调用完后它就没了,而且全局无法使用。这时候闭包就登场了。
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”变量对外不可见 ,同时你无法再次调用这个匿名的工厂方法来创建一个相同的对象 。