微信小程序示例使用到了大量的for+i+function+function组合代码到底怎么理解

在微信小程序示例代码里面使用到了非常多的for+i+function+function这种组合代码,有时看了头晕,到底是什么意思?起什么作用或者说解决什么问题?它跟javascript的closure(闭包)有什么关联?今天我们就来学习一下它。

下面使用一个作为例子:

var toastNum = 3

var pageData ={}

pageData.data ={}

for(var i =0; i <= toastNum; ++i) {

  pageData.data['toast'+i+'Hidden'] = true;

  (function (index) {

   pageData['toast'+index+'Change'] = function(e) {

      var obj = {}

      obj['toast'+index+'Hidden'] = true;

     this.setData(obj)

    }

   pageData['toast'+index+'Tap'] = function(e) {

      var obj = {}

      obj['toast'+index+'Hidden'] = false

     this.setData(obj)

    }

  })(i)

}

Page(pageData)

这段代码来自微信小程序示例代码: page/component/component-pages/wx-toast/wx-toast.js

       这段代码的代码的主要意思是通过一个for循环,把object对象pageData里的object变量data的toast0Hidden,toast1Hidden,toast2Hidden,toast3Hidden变量赋值都赋值成true,把object对象pageData里toast0Change,toast1Change,toast2Change,toast3Change变量分别赋值一个匿名回调函数,此回调函数如下:

function(e) {

      var obj = {}

     obj['toast'+index+'Hidden'] = true;

     this.setData(obj)

    }

把object对象pageData里toast0 Tap,toast1 Tap,toast2C Tap,toast3Tap变量分别赋值一个匿名回调函数,此回调函数如下:

function(e) {

      var obj = {}

     obj['toast'+index+'Hidden'] = false

     this.setData(obj)

}

但是为什么for循环里面还有一个

(function (index) {

……

})(i)

这样的东西呢?是不是多此一举,让代码复杂化,能不能去掉,如果不是不能,哪又起什么作用呢?

 

为了理解这个东西,我们先学习一点点javascript的作用域的知识

在javascript的世界里,只有全局作用域和函数作用域,没有块作用域,那么什么是全局作用域,什么又是函数作用域呢?全局作用域就是在全局范围都起作用的一些,其中囊括在函数之外定义的变量和函数内没有声明为var的变量,如果上面的toastNum,pageData,特别指出的是i它也是,而函数作用域就是在函数以内的作用范围,包括参(),函数体{}内,比如上面代码的var obj={}中的obj和函数参数index。

为了看到效果,我们把去掉,调整代码如下:

for(var i = 0; i<= toastNum; ++i) {

  pageData.data['toast'+i+'Hidden'] = true;

  pageData['toast'+i+'Change']= function(e) {

    var obj = {}

   obj['toast'+i+'Hidden'] = true;

   this.setData(obj)

  }

 pageData['toast'+i+'Tap'] = function(e) {

    var obj = {}

   obj['toast'+i+'Hidden'] = false

   this.setData(obj)

  }

}

调试时看变量初始化,好像都正常,该有的都有了


那咱们继续,点击界面上其中的某个按钮,调试结果:


调试的i,怎么变成4,进而形成toast4Hidden,从上上图我们知道,我们最高是3,怎么跑出4来了?哦,原来,i由于javascript里没有区块作用域,所以i现在全局作用域,并且只有一个i,当for循环完后i就变成了4,所以当回调函数使用它时就是4了,那么跟我们想的不一样,我们想的是当点击第一个btn时,就是相应的toast1Hidden,那怎么办?一种通用的就办法就引了函数作用域,就是javascript所说的closure(闭包),就是把i当参数传入一个函数,然后被传入的函数有一个参数是用来复制保存当时的i的,如下代码:

(function (index) {

……

})(i)

所以现在只有4个index变量(for循环以后),复制缓存i的四个状态:0,1,2,3,而这4个index的作用是函数作用域,在上面function(){}的{}里头有效,所以就可以实现我们之前想的目标,即函数里的index是对应的。

最后代码我贴一下,大家自己去体会下之间的不同:

Js文件代码:

var toastNum = 3

var pageData ={}

pageData.data ={}

for(var i = 0; i<= toastNum; ++i) {

  pageData.data['toast'+i+'Hidden'] = true;

  (function (index) {

    pageData['toast'+index+'Change'] =function(e) {

      var obj = {}

      obj['toast'+index+'Hidden'] = true;

      this.setData(obj)

    }

    pageData['toast'+index+'Tap'] = function(e){

      var obj = {}

      obj['toast'+index+'Hidden'] = false

      this.setData(obj)

    }

  })(i)

}

Page(pageData)

 

Wxml文件代码:

<viewclass="page">

  <view class="page__hd">

    <textclass="page__title">toast</text>

    <textclass="page__desc">toast提示</text>

  </view>

  <view class="page__bd">

    <view class="btn-area">

      <view class="body-view">

        <toasthidden="{{toast1Hidden}}" bindchange="toast1Change">

          默认

        </toast>

        <button type="default"bindtap="toast1Tap">点击弹出默认toast</button>

      </view>

      <view class="body-view">

        <toasthidden="{{toast2Hidden}}" icon="warn"bindchange="toast2Change">

          设置icon

        </toast>

        <button type="default" bindtap="toast2Tap">点击弹出设置icon的toast</button>

      </view>

      <view class="body-view">

        <toasthidden="{{toast3Hidden}}" duration="3000"bindchange="toast3Change">

          设置duration

        </toast>

        <button type="default"bindtap="toast3Tap">点击弹出设置duration的toast</button>

      </view>

    </view>

  </view>

</view>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值