Javascript闭包简单理解

原文: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");

 

时间: 2024-12-03 12:06:45

Javascript闭包简单理解的相关文章

JavaScript 闭包深入理解(closure)_javascript技巧

一.什么是闭包? "官方"的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话通俗的来说就是:JavaScript中所有的function都是一个闭包.不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的"闭包".看下面这段代码: function a() { var i = 0; function b() { a

javascript闭包的理解

 1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部变量,注意在函数内部定义变量时一定要使用var关键字,不带var关键字的变量为全局变量. javascript中每一段代码都有与之关联的作用域链,这个作用域链是一个对象列表或者链表,定义了这段代码"作用域"中的变量.顶层代码的作用域由全局变量组成:不包含嵌套的函数的作用域链有两个对象:一个是定义的函数参数和局部变量的对象,一个是全局变量对象:而嵌套函数

javascript闭包的理解_javascript技巧

1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部变量,注意在函数内部定义变量时一定要使用var关键字,不带var关键字的变量为全局变量. javascript中每一段代码都有与之关联的作用域链,这个作用域链是一个对象列表或者链表,定义了这段代码"作用域"中的变量.顶层代码的作用域由全局变量组成:不包含嵌套的函数的作用域链有两个对象:一个是定义的函数参数和局部变量的对象,一个是全局变量对象:而嵌套函数的

JavaScript 闭包深入理解(closure)

最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Javascript闭包的真实面目. -一.什么是闭包?"官方"的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话通俗的来说就是:JavaScript中所有的functio

javascript闭包的理解和实例_javascript技巧

顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域. with和eval除外,所以只能说JS的作用域机制非常接近词法作用域(Lexical scope). 下面是一个简单的使用全局变量的闭包实例: 复制代码 代码如下: var sWord="Hello,Welcome to web前端开发工程师的博客,请多多指教." function disWord(){ alert(sWord);

javascript闭包入门理解(非常详细)

之所以再写一篇闭包的文章,原因有二:一个是之前的文章写的不是很清楚,比较含糊.之前文章请看js闭包文章一 .原因二是闭包确实是js的难点和重点,不少网友也问过我,所以,决定再写一篇关于闭包的文章. 案例 首先看下闭包的一个简单案例 function A(){     function B(){        console.log("Hello haorooms!");     }     return B; } var c = A(); c();//Hello haorooms! 这

深入理解javascript闭包

变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域 变量的作用域无非就是两种:全局变量和局部变量 Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 var n=999; function f1(){ alert(++n); } f1(); // 1000 另一方面,在函数外部无法读取函数内的局部变量 function f1(){ var n=999; } alert(++n); // error 这里有一个地方需要注意,函数内部声明变量的时候,一定要

JavaScript闭包的一些理解

原文:JavaScript闭包的一些理解 简单一点的说:闭包就是能够读取其他函数内部变量的函数.那如何实现读取其它函数内部变量呢,大家都知道在JavaScript中内部函数可以访问其父函数中的变量,那如果将内部函数返回是不是代表能够通过它访问其父函数中的变量了呢,闭包的原理事实上就是这样. 摘录 闭包就是能够读取其他函数内部变量的函数.由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数". 闭包的主要作用: 可以读

Javascript高级教程:javascript闭包

文章简介:理解JavaScript的闭包是迈向高级JS程序员的必经之路,理解了其解释和运行机制才能写出更为安全和优雅的代码. 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){al