JS 深入理解, 一次性函数 匿名函数

看过jQuery源码的人应该知道,jQuery开篇用的就是立即执行函数。立即执行函数常用于第三方库,好处在于隔离作用域,任何一个第三方库都会存在大量的变量和函数,为了避免变量污染(命名冲突),开发者们想到的解决办法就是使用立即执行函数。

1.什么是立即执行函数(IIFE)

在了解立即执行函数之前先明确一下函数声明、函数表达式及匿名函数的形式,如下图:
在这里插入图片描述

接下来看立即执行函数的两种常见形式:( function(){…} )()和( function (){…} () ),一个是一个匿名函数包裹在一个括号运算符中,后面再跟一个小括号,另一个是一个匿名函数后面跟一个小括号,然后整个包裹在一个括号运算符中,这两种写法是等价的。要想立即执行函数能做到立即执行,要注意两点,一是函数体后面要有小括号(),二是函数体必须是函数表达式而不能是函数声明。先看下图:
在这里插入图片描述

从图中可以看出,除了使用()运算符之外,!,+,-,=等运算符都能起到立即执行的作用。这些运算符的作用就是将匿名函数或函数声明转换为函数表达式,如下图所示,函数体是函数声明的形式,使用运算符将其转换为函数表达式之后就可达到立即执行效果:
在这里插入图片描述

2.使用立即执行函数的好处

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

其中window即是全局对象。给其传入参数这样的好处是,可以缩短查询时的作用域链。作用域隔离非常重要,是一个JS框架必须支持的功能,jQuery被应用在成千上万的JavaScript程序中,必须确保jQuery创建的变量不能和导入他的程序所使用的变量发生冲突。

闭包和立即执行函数
  看个例子:

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

这个对象有其成员变量“speed”及成员函数“start”和“getspeed”,但是它的成员变量没有私有化,同时它也没有办法被继承。要实现对象的继承,你可以使用构造函数和原型继承。但怎么才能将成员变量私有化来实现对象的封装呢(而且有时候我们也不想那么麻烦使用原型)?有心的读者看了上面闭包的介绍,肯定马上有想法了。对,使用闭包!

function car() {
    var speed = 0;
    return { //返回的是一个对象
        start:function() {
            speed = 50;
        },
        getspeed:function () {
         return speed;
        }
    }
}
 
var car1 = car();
car1.start();
console.log(car1.getspeed()); //print 50

说了那么多,跟立即执行函数有什么关系呢。你再仔细看看上面的例子,你有了闭包函数来帮你创建“car”对象,这个函数就类似于工厂方法,它可以根据你的需要创建多个不同的对象。

不过开发的时候经常遇到这样的情况,就是我们希望对象只有一份,比如jQuery库的对象,它必须确保整个程序只有一份,多了也没有。在后端开发模式中,这叫单例模式,可以通过私有化构造函数来实现,那么在js里呢?

既然函数没法私有化,那么唯一的办法就是让这个工厂方法能且只能被调用一次。不能多次调用,那这个函数一定要是匿名函数;而且能被调用一次,那就必须在声明的时候立马执行。这时候,我们就可以邀请立即执行函数出场了:

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

很多人一开始会看错,认为对象“car”是一个函数,其实它是这个匿名的工厂方法执行完返回的对象,该对象拥有“start”和“getspeed”两个成员函数,而这两个函数所需要访问的“speed”变量对外不可见。同时你无法再次调用这个匿名的工厂方法来创建一个相同的对象。是不是很神奇?一个单例的,有着私有成员的对象就这么建好了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一次性函数(Immediately Invoked Function Expression,IIFE)是一种在声明时立即执行的JavaScript函数。这种函数通常用于在不污染全局命名空间的情况下,创建一个私有作用域来执行一些代码。 IIFE的基本语法如下: ``` (function() { // 这里是函数体 })(); ``` 在这个示例中,我们定义了一个匿名函数并立即执行它。由于这个函数是匿名的,我们不能直接调用它。因此,我们使用括号将函数包装起来,并在末尾添加另一个括号来立即执行它。 IIFE常用于创建私有变量和函数,以及在JavaScript中模拟块级作用域。例如,以下代码使用IIFE来创建一个私有作用域,并在其中定义一个私有变量`counter`,并暴露一个公共方法`increment`,用于增加计数器的值: ``` var counter = (function() { var count = 0; return { increment: function() { count++; console.log(count); } }; })(); counter.increment(); // 输出1 counter.increment(); // 输出2 counter.increment(); // 输出3 ``` 在这个示例中,我们定义了一个匿名函数并立即执行它,该函数返回一个对象,其中包含一个名为`increment`的方法。该方法在每次调用时将`count`变量增加1,并将当前计数器值输出到控制台。由于我们只暴露了`increment`方法,因此`count`变量是私有的,并且不能直接访问。每次调用`increment`方法时,都会在私有作用域内增加计数器的值,并将其输出到控制台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值