Javascript闭包用法实例分析


Posted in Javascript onJanuary 23, 2015

本文实例分析了Javascript闭包的概念及用法。分享给大家供大家参考。具体如下:

提到闭包,想必大家都早有耳闻,下面说下我的简单理解。
说实话平时工作中实际手动写闭包的场景并不多,但是项目中用到的第三方框架和组件或多或少用到了闭包。
所以,了解闭包是非常必要的。呵呵...

一、什么是闭包

简而言之,就是能够读取其他函数内部变量的函数。
由于JS变量作用域的特性,外部不能访问内部变量,内部可以外部变量。

二、使用场景

1. 实现私有成员。
2. 保护命名空间,避免污染全局变量。
3. 缓存变量。

先看一个封装的例子:

var person = function () {

    // 变量作用域为函数内部,外部无法访问

    var name = "default";
    return {

        getName: function () {

            return name;

        },

        setName: function (newName) {

            name = newName;

        }

    }

}();
console.log(person.name); // 直接访问,结果为:undefined

console.log(person.getName()); // 结果为:default

console.log(person.setName("langjt"));

console.log(person.getName()); // 结果为:langjt

再看循环中常用闭包解决引用外部变量问题:

var aLi = document.getElementsByTagName('li');

for (var i=0, len=aLi.length; i<len; i++) {

   aLi[i].onclick = function() {

     alert(i); // 无论点击哪个<li>元素,弹出的值都为len,表明这里的i和在for之后打印i的值是一样的。

   };

}

使用闭包后:
var aLi = document.getElementsByTagName('li');

for (var i=0, len=aLi.length; i<len; i++) {

  aLi[i].onclick = (function(i) {

    return function() {

      alert(i); // 此时点击<li>元素,就会弹出对应的下标了。

    }

  })(i);

}

三、注意事项

1. 内存泄漏

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题。
比如:

function foo() {

   var oDiv = document.getElementById(‘J_DIV');

   var id = oDiv.id;

   oDiv.onclick = function() {

     // alert(oDiv.id); 这里存在循环引用,IE低版本页面关闭后oDiv仍在内存中。所以尽可能缓存基本类型而不是对象。

     alert(id);

   };

   oDiv = null;

}

2. 变量命名

如果内部函数的变量和外部函数的变量名相同时,那么内部函数再也无法指向外部函数那个同名的变量。
比如:

function foo(num) {

  return function(num) {

    console.log(num); 

  }

}

var f = new foo(9);

f(); // undefined

其实上面的用法,专业术语叫函数柯里化(Currying),就是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。本质上也利用了闭包可以缓存的特性,比如:

var adder = function(num) {

    return function(y) {

        return num+y;

    };

};
var inc = adder(1);

var dec = adder(-1);

//inc, dec现在是两个新的函数,作用是将传入的参数值 (+/?)1

alert(inc(99));//100

alert(dec(101));//100 

alert(adder(100)(2));//102 

alert(adder(2)(100));//102

再比如阿里玉伯的seaJS源码中:

/**

 * util-lang.js - The minimal language enhancement

 */

function isType(type) {

  return function(obj) {

    return {}.toString.call(obj) == "[object " + type + "]"

  }

}
var isObject = isType("Object");

var isString = isType("String");

希望本文所述对大家的javascript程序设计有所帮助。

Javascript 相关文章推荐
javascript 操作cookies及正确使用cookies的属性
Oct 15 Javascript
js multiple全选与取消全选实现代码
Dec 04 Javascript
JavaScript使用addEventListener添加事件监听用法实例
Jun 01 Javascript
JS实现自动定时切换的简洁网页选项卡效果
Oct 13 Javascript
轻松使用jQuery双向select控件Bootstrap Dual Listbox
Dec 13 Javascript
javascript表单控件实例讲解
Sep 13 Javascript
原生js实现查询天气小应用
Dec 09 Javascript
JavaScript中的遍历详解(多种遍历)
Apr 07 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
Jul 14 Javascript
bootstrap table服务端实现分页效果
Aug 10 Javascript
vue 解决路由只变化参数页面组件不更新问题
Nov 05 Javascript
基于javascript实现放大镜特效
Dec 03 Javascript
JavaScript学习笔记之Function对象
Jan 22 #Javascript
JavaScript学习笔记之Cookie对象
Jan 22 #Javascript
javascript二维数组转置实例
Jan 22 #Javascript
JavaScript学习笔记之内置对象
Jan 22 #Javascript
JavaScript学习笔记之JS事件对象
Jan 22 #Javascript
jquery实现搜索框常见效果的方法
Jan 22 #Javascript
JavaScript学习笔记之定时器
Jan 22 #Javascript
You might like
PHP 页面跳转到另一个页面的多种方法方法总结
2009/07/07 PHP
PHP实现读取一个1G的文件大小
2013/08/24 PHP
PHP中使用memcache存储session的三种配置方法
2014/04/05 PHP
百度地图API应用之获取用户的具体位置
2014/06/10 PHP
php微信公众账号开发之前五个坑(一)
2016/09/18 PHP
PHP一致性hash分布式算法封装类定义与用法示例
2018/08/04 PHP
PHP封装类似thinkphp连贯操作数据库Db类与简单应用示例
2019/05/08 PHP
jQuery.getScript加载同域JS的代码
2012/02/13 Javascript
js 单击式的下拉菜单效果实例
2013/08/13 Javascript
控制台报错object is not a function的解决方法
2014/08/24 Javascript
jQuery对val和atrr(&quot;value&quot;)赋值的区别介绍
2014/09/26 Javascript
JavaScript实现网页截图功能
2014/10/16 Javascript
深入解析JavaScript编程中的this关键字使用
2015/11/09 Javascript
浅谈JS原型对象和原型链
2016/03/02 Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
2016/10/11 Javascript
详解vue-cli本地环境API代理设置和解决跨域
2017/09/05 Javascript
Angular4学习教程之HTML属性绑定的方法
2018/01/04 Javascript
p5.js码绘“跳动的小正方形”的实现代码
2019/10/22 Javascript
vue实现简单跑马灯效果
2020/05/25 Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
2020/07/28 Javascript
浅谈vue 二级路由嵌套和二级路由高亮问题
2020/08/06 Javascript
Python的Django REST框架中的序列化及请求和返回
2016/04/11 Python
Python 字典与字符串的互转实例
2017/01/13 Python
python用Pygal如何生成漂亮的SVG图像详解
2017/02/10 Python
Python处理Excel文件实例代码
2017/06/20 Python
Django单元测试中Fixtures用法详解
2020/02/25 Python
记录一下scrapy中settings的一些配置小结
2020/09/28 Python
您的健身减肥和健康饮食专家:vitafy
2017/06/06 全球购物
Java程序员面试90题
2013/10/19 面试题
书法培训心得体会
2014/01/05 职场文书
党组织公开承诺书
2014/03/29 职场文书
2016教师节问候语
2015/11/10 职场文书
MySQL安装后默认自带数据库的作用详解
2021/04/27 MySQL
关于golang高并发的实现与注意事项说明
2021/05/08 Golang
Oracle用户管理及赋权
2022/04/24 Oracle
MySQL使用IF语句及用case语句对条件并结果进行判断 
2022/09/23 MySQL