博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初识JavaScript闭包
阅读量:5008 次
发布时间:2019-06-12

本文共 1613 字,大约阅读时间需要 5 分钟。

一个问题引发的思考

在我学习javascript的事件时,有一个小任务是使用JS来实现 li 列表项在鼠标悬浮时会有背景阴影的动态效果,很自然想到用for 来为每个列表项添加onmouseover 和 onmouseout事件来改变和恢复 li 的类名。

如下:

1 

 

看起来很有道理的代码会什么不能正常工作?

先看一下为什么

在第8行和11行,通过改变 li 元素的classname来实现鼠标悬浮的动态效果改变,根据我以前学习的语言(C和JAVA)这明显是不对的,怎么能在函数内使用外面的局部变量呢,可是浏览器为什么没有报错,我在7行加了一句console.log(i);看一下

浏览器输出了3 并报错:closure.html:44 Uncaught TypeError: Cannot set property 'className' of undefined

当这两个事件发生时,函数会执行,函数会访问Lis 和 i 这两个变量,但是注意循环和事件函数不是同时执行的,事件函数发生时i的 已经是3了, 而Lis里并没有Lis[3]这个元素。

可是这两个函数为什么能访问外面的局部变量呢,答案是 闭包 (closure)

闭包初识

 闭包就是在创建函数时为其保存一份创建时的外部环境,所以这两个事件函数能够访问到i这个变量,虽然访问的是循环执行完后的i的值。这也已经很神奇了对吧,源自函数式编程的魔法。那么怎么让其访问的 i 是函数自身被创建时的 i 呢,我再创建一个函数专门用来返回这个事件函数,如下:

1   function makeevents(i) { 2     console.log(i); 3     return function() { 4       Lis[i].className = "lihover"; 5     } 6   } 7  8   function addevent() { 9     for (var i = 0; i < Lis.length; i++) {10       Lis[i].onmouseover = makeevents(i);11       Lis[i].onmouseout = function() {12         this.className = "";13       }14     }15   }16   addevent();

我只是在mouseover事件用了这个机制,在mouseout使用了this关键词这个等最后在讨论。

在浏览器里运行一下发现效果已经实现了,并且在页面加载完后控制台就打印出了0 1 2 

makeevent函数的作用正是创建闭包,在每一次循环创建一个,这样Lis[i]引用的就是正确的 li 元素了,看起来好像很繁琐的样子,事实上我们因为可以对makeevent传入参数来改变返回的函数的一些特点。这好像面向对象的工厂模式对吧。事实上我们完全可以用闭包来实现面向对象的封装。

关于this

我在第二个事件函数里使用了this,它表示了响应这个事件的当前对象,也即表示当前的列表项。并且在必要时还可以往Lis[i]元素对象里加入其他东西,如下:

Lis[i].index = i;      Lis[i].hehe = "hehe";      Lis[i].onmouseout = function() {        console.log(this.hehe);        Lis[this.index].className = "";      }

这样写也是可以的。通过对象本身可以动态的添加属性这一个JavaScript的特点来完成的。

是的,JavaScript真是一门神奇的语言

转载于:https://www.cnblogs.com/pompey/p/5848914.html

你可能感兴趣的文章
Django模板语言相关内容
查看>>
前端开发工程师如何在2013年里提升自己【转】--2016已更新升级很多何去何从?...
查看>>
markdown语法测试集合
查看>>
running and coding
查看>>
实现QQ第三方登录、网站接入
查看>>
HTML CSS 层叠样式表 三
查看>>
Qt pro pri 文件学习1
查看>>
软件工程概论第六周学习进度条
查看>>
[思路]导入导出功能
查看>>
【iOS】UICollectionView自己定义Layout之蜂窝布局
查看>>
【以太坊钱包开发 一】MyEtherWallet 钱包开发项目概述
查看>>
golang——(strings包)常用字符串操作函数
查看>>
发布aar到jcenter
查看>>
跨浏览器问题的五种解决方案
查看>>
XPath定位时,使用文本的方法小技巧。
查看>>
安装pandas报错(AttributeError: 'module' object has no attribute 'main')
查看>>
ch02 fundamental definition 01
查看>>
JSON解析
查看>>
Position is everything?(css定位学习的一些心得)(一)
查看>>
如何提高编程水平
查看>>