前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解JavaScript的匿名函数(文末有教程分享)

详解JavaScript的匿名函数(文末有教程分享)

作者头像
用户10106350
发布2022-10-28 11:25:14
6700
发布2022-10-28 11:25:14
举报
文章被收录于专栏:WflynnWeb

什么是匿名函数:没有实际名字的函数

匿名函数的作用:

1、通过匿名函数可以实现闭包(必须掌握的知识点)

2、模拟块级作用域,减少全局变量。执行完匿名函数,存储在内存中相对应的变量会被销毁,使用块级作用域,会大大降低命名冲突的问题,不必担心搞乱全局作用域了。

详解匿名函数:

声明一个普通函数:

代码语言:javascript
复制
function zxx () {
    console.log('good girl')
}

将函数的名字去掉

代码语言:javascript
复制
function () { // 此时浏览器会报错
    console.log('good girl')
}

正确定义的匿名函数

代码语言:javascript
复制
(function () {
    // 由于没有执行该匿名函数,所以不会执行匿名函数体内的语句。
    console.log('zxx')
})

对去掉名字的函数加入括号后就是一个匿名函数了:

小括号的作用:

小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,实际上小括号返回的就是一个匿名函数的Function对象。因此,小括号对加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。所以如果在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式。通俗点讲就是,加入小括号后就实现了和具名函数一样的形式。

匿名函数自执行,也称为立即执行函数表达式(IIFE)

方式一

代码语言:javascript
复制
    // 无参数的匿名函数
    (function () {
        console.log('zxx')
    })();
 
    // 带参数的匿名函数
    (function (a, b, c) {
        console.log('参数一:', a) // 参数一: 这是普通函数传参的地方
        console.log('参数二:', b) // 参数二: 我是参数二
        console.log('参数三:', c) // 参数三: zxx
    })('这是普通函数传参的地方', '我是参数二', 'zxx')

方式二

代码语言:javascript
复制
    // 推荐使用
    (function () {
        console.log('zxx')
    }())

方式三

代码语言:javascript
复制
    !function (zxx) {
        console.log(zxx)
    }('zxx')

方式四

代码语言:javascript
复制
    let zxx = function (zxx) {
        console.log(zxx)
    }('zxx')

IIFE常用用法

代码语言:javascript
复制
    IIFE 的另一个非常普遍的进阶用法是把它们当作函数调用并传递参数进去。
    var a = 2;
    (function IIFE (global) {
        var a = 3
        console.log(a) // 3
        console.log(global.a) // 2
    })(window)
    console.log(a) // 2
 
    IIFE 还有一种变化的用途是倒置代码的运行顺序,
    将需要运行的函数放在第二位,
    在 IIFE 执行之后当作参数传递进去
    var a = 2;
    (function IIFE (def) {
        def(window)
    })(function def (global) {
        var a = 3
        console.log(a) // 3
        console.log(global.a) // 2
    })

匿名函数应用场景

代码语言:javascript
复制
    1.事件
    $('#zxx').onclick = function () {
        console.log('给按钮添加点击事件')
    }
 
    2.对象
    var obj = {
        name: 'zxx',
        zxx: function () {
            return this.name + ' is' + ' good girl'
        }
    }
    console.log(obj.zxx()) // zxx is good girl
    
    3.函数表达式
    var zxx = function () {
        return 'zxx is good girl'
    }
    console.log(zxx()) // zxx is good girl
 
    4.回调函数
    setInterval(function () {
        console.log('zxx is good girl')
    }, 1000)
 
    5.作为函数的返回值
    function zxx () {
        // 返回匿名函数
        return function () {
            return 'zxx'
        }
    }
    console.log(zxx()()) // zxx

匿名函数模仿块级作用域

代码语言:javascript
复制
    if (true) {
        var a = 12 // a为全局变量
    }
    console.log(a) // 12
 
    for (var i = 0; i < 3; i++) {
        // console.log(i)
    }
    console.log(i) // 3 for没有自己的作用域,所以当循环结束后i就成为全局变量
    if () {}for () {} 等没有自己的作用域。
    如果有,出了自己的作用域,
    声明的变量就会立即被销毁了。
    但可以通过匿名函数来模拟块级作用域:
 
    function fn () {
        (function () { // 这里是我们的块级作用域(私有作用域) 
            var zxx = 'good girl!' // 此变量在外部并未定义
            console.log(zxx) // good girl!
        })()
        console.log(zxx) // 报错Uncaught ReferenceError: zxx is not defined
    }
    fn()

习题一

代码语言:javascript
复制
function test(a, b, c, d){
    console.log(a + b + c + d);
}(1, 2, 3, 4);
// 不执行也不报错
 
 
==============
 
function test(){
    console.log(a + b + c + d);
}();
// 报错:Uncaught SyntaxError: Unexpected token )

习题二

代码语言:javascript
复制
function zxxFn (){
    var arr = [];
    for(var i = 0; i < 10; i ++){
        arr[i] = function (){
            console.log(i);
        }
    }
    return arr;
}
var zxx = zxxFn();
for(var j = 0; j < 10; j++){
    zxx[j]();
}

详解

zxxFn中由于for不是块级作用域,所以var i 变成 zxxFn的局部变量,每次新的i都会覆盖原来的,最终i=10。所以会输出10个10

习题三

代码语言:javascript
复制
function zxxFn(){
    var arr = [];
    for(var i = 0; i < 10; i ++){
        (function(j){
            arr[i] = function (){
            console.log(j + " ");
        }
        }(i))
    }
    return arr;
}
var zxx= zxxFn();
for(var j = 0; j < 10; j++){
    zxx[j]();
}

详解:

这题使用了立即执行函数,把zxxFn中的i当参数传给了,匿名函数的j,所以每次执行j的状态都会更新,所以会输出0 1 2 3 4 5 6 7 8 9

匿名函数的缺点

1. 匿名函数在栈追踪中不会显示出有意义的函数名,使得调试很困难。

2. 如果没有函数名,当函数需要引用自身时只能使用已经过期的 arguments.callee 引用, 比如在递归中。另一个函数需要引用自身的例子,是在事件触发后事件监听器需要解绑自身。

3. 匿名函数省略了对于代码可读性 / 可理解性很重要的函数名。一个描述性的名称可以让代码不言自明。

JavaScript高级教程链接:https://pan.baidu.com/s/14mHL6DvlwwfDN9A0UX6hiQ

提取码:hnv4

我曾以为对一个人的思念,会从有到无,会是个渐渐消减的过程,但事实上,它会在某一刻突然立减为零,又会在另一个瞬间突然发疯似的想念,这种崩溃又矛盾的感觉直击心灵。昨天的自己或许还能振作,今天的自己就只能崩溃,那就再崩溃两小时吧。是啊。总会过去的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WflynnWeb 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档