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));//
- alert(dec(101));//100
- alert(adder(100)(2));//102
- alert(adder(2)(100));//
再比如阿里玉伯的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闭包的理解
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 在开始了解闭包前我们必须要先理解JavaScript的变量作用域. 一.变量的作用域无非就是两 ...
- javascript闭包的理解
闭包是Javascript的一个难点,但也是一个很重要的知识点. 1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部 ...
- 我对 javascript 闭包的理解
学js的学到闭包,但是理解不深. 后来看了一下这篇文章: 地址:http://leepiao.blog.163.com/blog/static/4850313020112835355917/ 内容如下 ...
- JavaScript闭包简单应用
闭包定义 在JavaScript中,当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包.简单说,闭包就是能够读取其他函数内部变量的函数. 闭包的作用: 1. 可以读取函数内部的变量 2. 让 ...
- javascript 闭包的理解(一)
过很多谈如何理解闭包的方法,但大多数文章,都是照抄或者解释<Javascript高级程序设计(第三版)>对于闭包的讲解,甚至例程都不约而同的引用高程三181页‘闭包与变量’一节的那个“返回 ...
- javascript闭包的理解和实例
所谓闭包,值得是词法表示包括不必要计算的变量的函数,也就是说,该函数可以使用函数外定义的变量. 顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通 ...
- 关于Javascript 闭包的理解
一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...
- 关于Javascript闭包的理解
以下内容属个人理解,如有看不明白或漏洞之处,纯属水平不佳,还望见谅. 关于闭包,高程里的定义是:指有权访问另一个函数作用域中的变量的函数.创建闭包最常见的方法就是在一个函数的内部再创建一个函数. 这里 ...
- python 装饰器、内部函数、闭包简单理解
python内部函数.闭包共同之处在于都是以函数作为参数传递到函数,不同之处在于返回与调用有所区别. 1.python内部函数 python内部函数示例: def test(*args): def a ...
随机推荐
- -_-#【CSS3】CSS3 gradient transition with background-position
CSS3 gradient transition with background-position <!DOCTYPE html> <html> <head> &l ...
- 解决weblogic Managed Server启动非常慢的情况
jdk版本:1.7.0_79 查看控制台日志停留在如下地方: . . JAVA Memory arguments: -Xms2048m -Xmx4096m -XX:MaxPermSize=512m . ...
- MongoDB主从配置
master的配置 # cat mongod.conf dbpath = /app/sinova/mongodata/db #指定数据库目录 logpath = /app/sin ...
- (转载)HTML标签<br><br/>的区别在哪里?
(转载)http://zhidao.baidu.com/question/259205863.html HTML标签<br><br/>的区别在哪里? 如果一样为什么还要分2个标 ...
- Linux下动态库的使用
1.生成动态库: gcc -fPIC -shared -o libdemo.so demo.c 考虑程式库major的升级会破坏兼容性:而minior的升级则可能不会,一般建议用以下方式来生成动态库. ...
- (转)【C++ STL】细数C++ STL 的那些事 -- priority_queue(优先队列)
装载自http://blog.csdn.net/tianshuai1111/article/details/7652553 一,概述 priority_queue是拥有权值观念的queue,它允许加入 ...
- JVM垃圾回收机制入门
前言 数据库是大家会普遍重视的一个领域,异步通信一般用不到,虚拟机在大部分时候不会出问题,常被人忽视,所以我打算先学习虚拟机,从零单排Java高性能问题. 堆内存存储结构 Java6是以年代来规划内存 ...
- 最长回文 HDU 3068 (裸的Manacher)
直接看代码: ============================================================================================= ...
- Servlet的一些细节(1)
1. Servlet程序必须映射到一个URL地址 由于客户端是通过URL访问web服务器资源,所以Servlet程序必须映射到一个URL地址.这个工作在web.xml文件中使用<servlet ...
- Maven deploy
1.在maven/conf/setting.xml中: 在<servers>中加入 <server> <id>internal</id> <u ...