Javascript 进阶 5-5 闭包进阶:工厂模式及私有方法

首先我们先来看看下面的例子

// 申论题function  arrFunction () {    var arr = [];    for (var i = 0; i < 3; i++) {        arr.push(function () {            console.log(i);        });    }    return arr;}var fn = arrFunction();fn[0]();fn[1]();fn[2]();

请问各位,觉得会分别印出多少呢结果呢?

http://img2.58codes.com/2024/201217700dqb8DoxRX.png

可以看到都是印出 i = 3 的状况

那么我们先来检查一下 fn 里面是甚么

http://img2.58codes.com/2024/20121770D14H00JBJN.png

如同预期, fn 里面是我们 push 进去的三段函式,而里面参照的 i 很明显是在 () 父层宣告的变数。

那么为什么会都取得3呢? 在这个地方要思考一下, 我们在执行这个闭包的时候,父层的全域变数并非一成不便喔,我们可以透过不同的方式去控制他,这个地方我们可以换一个方式检视。

// 申论题function  arrFunction () {    var arr = [];    for (var i = 0; i < 3; i++) {        arr.push(function () {            console.log(i);        });    }        console.log('i', i); // 加这行    return arr;}var fn = arrFunction();fn[0]();fn[1]();fn[2]();

http://img2.58codes.com/2024/20121770V812N0JtRB.png

也就是说,在执行完这个 for 迴圈的时候呢,i就已经是3了,而我们事后再进行呼叫的话,当然就都是印出3瞜!

那如果我们想要的是依序印出 0 1 2 的话该怎么做?

可以利用到我们之前介绍到的立即函式 IIFE 进行修改,其中的一个功能就是限制作用域

// 申论题function  arrFunction () {    var arr = [];    for (var i = 0; i < 3; i++) {        (function (j) { // 改成 j            arr.push(function () {                 console.log(j); // 改成印出 j            });        })(i); // 每次累加的 i 都传入立即函式中    }    return arr;}var fn = arrFunction();fn[0]();fn[1]();fn[2]();

透过这样的方式就可以印出 0 1 2 结果瞜!

那么另外还有一种方式,是通过 ES6 let 的宣告函示的方法, 也可以印出 0 1 2 这样结果的方式

// 申论题function  arrFunction () {    var arr = [];    for (let i = 0; i < 3; i++) {        arr.push(function () {            console.log(i);        });    }    return arr;}var fn = arrFunction();fn[0]();fn[1]();fn[2]();

好的,接下来看上一篇文章介绍到的例子~

function storeMoney() {    var money = 1000;    return function (price) {        money = money + price;        return money;    }}

这边我们在父层的变数中也不必固定一定要 1000,可以优化成预设变数的样子

// 函式工厂function storeMoney (initValue) {    var money = initValue || 1000;    return function (price) {        money = money + price;        return money;    }}var MingMoney = storeMoney(100);console.log(MingMoney(500));

这样的感觉又称为 函式工厂,透过这个函式工厂,你可以给他不同的值,但是呢又会做相同的事情。

除此之外,闭包还有另外一种形式叫做 私有方法

我们沿用上方的例子,我们执行这个 storeMoney 里面回传的子函式,但它都只会做一样的事情,就是把传入的数值累加,但是实际状况并不是只有加钱啊,小明应该也会想花钱吧!也会想知道现在有多少钱吧!

那我们该怎么满足这样的需求呢? 就是利用 私有方法 定义不同的方法!

// 函式工厂function storeMoney (initValue) {    var money = initValue || 1000;    // 私有方法    return {        increase: function (price) {            money += price;        },        decrease: function (price) {            money -= price;        },        value: function (price) {            return money;        }    }}

我们在原本要回传函式的地方回传了一个物件,物件中包含了许多可能会用到的私有方法

这样很明显,如果我们需要调用的时候呢,就可以

var MingMoney = storeMoney(100);MingMoney.increase(100);MingMoney.increase(100);MingMoney.increase(300);MingMoney.increase(290);MingMoney.decrease(310);console.log(MingMoney.value());

透过这样的方式呢,我们就可以让一个闭包的功能得到不同面向的实用性。

也可以针对不同的需求写出不同的 闭包 function,透过不同的分类来管理不同的办法。

好的~今天的文章就先到这里噜,希望对各位有帮助!汪汪~


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章