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判断用户浏览器插件安装情况的代码
Jan 01 Javascript
jquery中插件实现自动添加用户的具体代码
Nov 15 Javascript
JS常用函数使用指南
Nov 23 Javascript
jQuery多文件异步上传带进度条实例代码
Aug 16 Javascript
Bootstrap table的使用方法
Nov 02 Javascript
微信小程序开发之相册选择和拍照详解及实例代码
Feb 22 Javascript
Vue指令的钩子函数使用方法
Mar 20 Javascript
细说webpack源码之compile流程-入口函数run
Dec 26 Javascript
浅谈angularJs函数的使用方法(大小写转换,拷贝,扩充对象)
Oct 08 Javascript
axios封装,使用拦截器统一处理接口,超详细的教程(推荐)
May 02 Javascript
Vue实现商品分类菜单数量提示功能
Jul 26 Javascript
解决antd的Form组件setFieldsValue的警告问题
Oct 29 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脚本数据库功能详解(下)
2006/10/09 PHP
str_replace只替换一次字符串的方法
2013/04/09 PHP
php中stdClass的用法分析
2015/02/27 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
JS格式化数字保留两位小数点示例代码
2013/10/15 Javascript
JS方法调用括号的问题探讨
2014/01/24 Javascript
JS实现鼠标单击与双击事件共存
2014/03/08 Javascript
jquery操作select方法汇总
2015/02/05 Javascript
JS实现带圆弧背景渐变效果的导航菜单代码
2015/10/13 Javascript
浅析四种常见的Javascript声明循环变量的书写方式
2015/10/14 Javascript
初识angular框架后的所思所想
2016/02/19 Javascript
JavaScript判断微信浏览器实例代码
2016/06/13 Javascript
浅谈Angular.js中使用$watch监听模型变化
2017/01/10 Javascript
Base64(二进制)图片编码解析及在各种浏览器的兼容性处理
2017/02/09 Javascript
Restify中接入Socket.io报Error:Can’t set headers的错误解决
2017/03/28 Javascript
jQuery Ajax使用FormData上传文件和其他数据后端web.py获取
2017/06/11 jQuery
基于AngularJS实现的工资计算器实例
2017/06/16 Javascript
vue中的模态对话框组件实现过程
2018/05/01 Javascript
JS通过位运算实现权限加解密
2018/08/14 Javascript
世界上最短的数字判断js代码
2019/09/09 Javascript
Vuex中实现数据状态查询与更改
2019/11/08 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
2020/03/23 Javascript
Jquery+javascript实现支付网页数字键盘
2020/12/21 jQuery
[05:31]DOTA2英雄梦之声_第08期_莉娜
2014/06/23 DOTA
Python中使用pprint函数进行格式化输出的教程
2015/04/07 Python
MySQL适配器PyMySQL详解
2017/09/20 Python
Python递归函数实例讲解
2019/02/27 Python
Python3中编码与解码之Unicode与bytes的讲解
2019/02/28 Python
python SVD压缩图像的实现代码
2019/11/05 Python
python使用协程实现并发操作的方法详解
2019/12/27 Python
css3之UI元素状态伪类选择器实例演示
2017/08/11 HTML / CSS
Forever 21美国官网:美国标志性快时尚品牌
2017/02/20 全球购物
美容院员工规章制度
2015/08/05 职场文书
React如何创建组件
2021/06/27 Javascript
JVM的类加载器和双亲委派模式你了解吗
2022/03/13 Java/Android
Oracle数据库中通用的函数实例详解
2022/03/25 Oracle