SAP Fiori开发中的JavaScript基础知识13 - 闭包,模块模式,回调函数(示例补充)

1. 前言

在上一篇博客中,我介绍了JavaScript中闭包,模块和回调的概念,这些概念理解起来相对复杂。

在本篇博客中,我将通过例子,进一步解释这些概念。

2. 示例

2.1 模块模式的封装

首先让我们封装一个HouseInspector的模块,用于检查house对象。

在这个HouseInspector模块中,定义私有变量lastCheckResult用于存储上一次的检查结果。同时,返回对象中包含两个暴露的方法,方法CheckLight用于检查house对象中light的情况,方法getLastCheckResult用于返回检查结果。

在外部调用时,仅可访问HouseInspector模块所暴露的方法,HouseInspector模块内部的变量对外是不可见的。

var HouseInspector = (function () {

    var lastCheckResult = "No check yet";

    return {
        checkLight: function (house) {
            if (house.windows >= 4) {
                lastCheckResult = 'Enough light';
            } else {
                lastCheckResult = 'Too dark!';
            }
        },

        getLastCheckResult: function () {
            return lastCheckResult;
        }
    }

})();

var house = {
    window: 3,
    people: [],
    enter: function (name) {
        this.people.push(name);
    },
    whoIsIn: function () {
        for (var index = 0; index < this.people.length; index++) {
            console.log(this.people[index]);
        }
    }
};

// test 1
HouseInspector.checkLight(house);
let checkResult = HouseInspector.getLastCheckResult();
console.log(checkResult);  // 运行结果:Too dark!

通过调用HouseInspector模块提供的公共方法,我们可以完成对house对象的检查,并拿到检查结果。

2.2 闭包特性

接下来,让我们测试一下闭包的特性。

在HouseInspector中定义一个私有变量inspectionTimes, 用于记录执行检查的次数。然后连续使用HouseInspector来检查两个house对象。


var HouseInspector = (function () {

    var lastCheckResult = "No check yet";
    var inspectionTimes = 0;

    return {
        checkLight: function (house) {
            if (house.windows >= 4) {
                lastCheckResult = 'Enough light';
            } else {
                lastCheckResult = 'Too dark!';
            }

            inspectionTimes++;
            
        },

        getLastCheckResult: function () {
            return lastCheckResult;
        },

        getInspectionTimes: function (){
            return inspectionTimes;
        }
    }

})();

var house = {
    window: 3,
    people: [],
    enter: function (name) {
        this.people.push(name);
    },
    whoIsIn: function () {
        for (var index = 0; index < this.people.length; index++) {
            console.log(this.people[index]);
        }
    }
};

// test
HouseInspector.checkLight(house);
HouseInspector.checkLight(house);
let count = HouseInspector.getInspectionTimes( );
console.log(count); // 运行结果:2

可以看到,运行结果为2。这也就意味着,模块内的私有变量,仍会会一直保持,即使外部调用结束后。

类比:JavaScript中闭包的这种特性,有点类似于ABAP中单例模式的效果,也即在一个线程内,单例内部的属性会一致保持。(当然,也可以类比成,一个类的静态属性Static Attribute)

2.3 回调函数的使用

结合上例,让我们为HouseInspector模块的checkLight方法定义出一个回调函数的参数。

在使用时,我们创建出所需要回调函数,并将这个函数作为参数传递给HouseInspector模块的checkLight方法,这样,调用方就可以通过回调函数来影响函数的执行行为了。

在下例中,我们创建了两个不同功能的回调函数printResult和showResult,并在调用时传递给服务方。

var HouseInspector = (function () {
    //Stored last result with initial value
    var lastCheckResult = "No check yet";

    return {
        //Function to check the light
        checkLight: function (house, fnResultHandler) {
            if (house.windows >= 4) {
                lastCheckResult = 'Enough light';
            } else {
                lastCheckResult = 'Too dark!';
            }

            //if a callback function was given, call it with the result
            if (fnResultHandler && typeof (fnResultHandler) === 'function') {
                fnResultHandler(lastCheckResult);
            }
        },

        //Function to get the last stored result
        getLastCheckResult: function () {
            return lastCheckResult;
        }
    }

})();

var house = {
    window: 3,
    people: [],
    enter: function (name) {
        this.people.push(name);
    },
    whoIsIn: function () {
        for (var index = 0; index < this.people.length; index++) {
            console.log(this.people[index]);
        }
    }
};

//callback function 1: print the result to the console
function printResult(result) {
    console.log(result);
}

//callback function 2: show a popup with the result
function showResult(result) {
    //alert(result);
    console.log('<< window >>');
    console.log(result);
    console.log('<< window >>');
}

//test
HouseInspector.checkLight(house);
HouseInspector.getLastCheckResult();
HouseInspector.checkLight(house, printResult); //运行结果:Too dark!
HouseInspector.checkLight(house, showResult);  //运行结果:<< window >> Too dark! << window >>

可以看到,通过传入回调函数的不同,我们可以得到不同的运行结果。

类比:JavaScript中回调函数的概念,与ABAP编程中回调的思想是类似的,都是通过提前“注册”一个预期执行的行为给服务方。
只不过在JavaScript中,这种“注册”的方式是通过函数实现的,而在ABAP中,更多的是通过接口实现的。
(当然,在ABAP中,这种回调的思想,也可以通过Function实现,但并非将function作为输入参数,而是通过预先设计的配置表,将回调函数配置到配置表中)

3. 小结

本文通过示例,进一步解释了JavaScript中闭包,模块和回调的概念,并类比了ABAP中相关概念的实现方式。希望本文对你有帮助!

  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年铸器

给作者赏杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值