好程序员技术分析JavaScript闭包特性详解

简介: 好程序员技术分析JavaScript闭包特性详解,今天来总结一下js闭包的那些事,以及遇到的坑和解决方法,希望对你有所帮助。是的,没看错标题,重要的事情要说三篇,JavaScript闭包。首先先简要总结闭包特性:函数的局部变量在函数返回之后仍然可用栈上的内存空间在函数返回之后仍在存在,不被回收给个例子。

好程序员技术分析JavaScript闭包特性详解,今天来总结一下js闭包的那些事,以及遇到的坑和解决方法,希望对你有所帮助。
是的,没看错标题,重要的事情要说三篇,JavaScript闭包。
首先先简要总结闭包特性:
函数的局部变量在函数返回之后仍然可用
栈上的内存空间在函数返回之后仍在存在,不被回收
给个例子。下面这段代码会返回一个函数的引用:
function sayHello2(name) {

var text = 'Hello ' + name; // Local variable
var sayAlert = function() { alert(text); }
return sayAlert;

}
say2 = sayHello2('Bob');
say2(); // alerts "Hello Bob"
对于这段代码,C程序员可能会认为sayAlert和say2一样,都是指向一个函数的指针。但实际上它俩有一个重要区别: 在JavaScript中,你可以认为一个函数的指针变量同时拥有两个指针。一个指向这个函数,另一个隐藏的指针指向一个闭包。
重点在于你的函数内是否引用的外部变量。
在JavaScript中,如果你在一个函数内定义一个新的函数,那么这个新的函数就是一个闭包。 对于C或者其他高级语言,函数执行结束并返回之后,它所占用的栈空间将被释放回收。函数内定义的局部变量将不再可用。但在JavaScript中,并不这样。如上所示,函数执行结束后,它所占用的栈空间并不会被全部回收。
上面是基本理论。更进一步,再来一个例子:
//code from http://www.goodprogrammer.org/html5_class.shtml function say667() {

// Local variable that ends up within closure
var num = 666;
var sayAlert = function() { alert(num); }
num++;
return sayAlert;

}
var sayNumber = say667();
sayNumber(); // alerts 667
这个例子说明:闭包中使用的函数局部变量并非是值拷贝,而是引用。say667()执行结束之后number所在的那块内存的值为667,而sayNumber()是在say667()执行结束之后才执行,当它访问number所在的内存时,结果自然也是667。
再进一步,看看用closure时易发生的错误的例子:
function buildList(list) {

var result = [];
for (var i = 0; i < list.length; i++) {
    var item = 'item' + list[i];
    result.push( function() {alert(item + ' ' + list[i])} );
}
return result;

}

function testList() {

var fnlist = buildList([1,2,3]);
// Using j only to help prevent confusion -- could use i.
for (var j = 0; j < fnlist.length; j++) {
    fnlist[j]();
}

}
时刻保持清醒:变量是在内存里的,闭包使用的是内存的引用而不是那块内存的值拷贝。
当你在循环中定义函数(闭包)的时候得小心,它可能并不像你最开始想的那样工作。关键有两个:
子函数使用的是外部函数的局部变量的引用。
循环内只是定义了子函数,并没有执行这个字函数。
最后,来一个最抽象的例子:
function newClosure(someNum, someRef) {

// Local variables that end up within closure
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
return function(x) {
    num += x;
    anArray.push(num);
    alert('num: ' + num +
        '\nanArray ' + anArray.toString() +
        '\nref.someVar ' + ref.someVar);
  }

}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;
这个例子说明,闭包的创建时机是在函数被调用的时候。每次函数调用都会生成一个新的闭包,也就是一块新的内存区域。因为函数每次调用都会新分配一块栈内存,这是一回事。
最后我自己来总结一下闭包:
函数的局部变量在其他地方被引用
闭包有两种基本情况:闭包的返回值是一个函数,它其中使用了该闭包的局部变量;闭包内定义了内部函数,内部函数引用了闭包的局部变量
每次函数调用,都会生成一个新的闭包,分配新的内存
实例:(滑过tab)
window.onload= function(){
var tits = $('#tabTit1 li');
var cons = $('#tabCon1 .con');
var len = cons.length;
var liChange = function(){
for(var n=0;ntits[n].className = tits[n].className.replace(/s*cur/g,'');
cons[n].className = cons[n].className.replace(/s*cur/g,'');
}
}
for(var i = 0; itits[i].i = i;
tits[i].onmouseover = function(){
liChange();
cons[this.i].addClass('cur');
tits[this.i].addClass('cur');
}
}
};

相关文章
|
20天前
|
JavaScript
闭包(js的问题)
闭包(js的问题)
12 0
|
1月前
|
设计模式 JavaScript 前端开发
js开发:请解释闭包(closure)是什么,以及它的用途。
闭包是JavaScript中的关键特性,允许函数访问并操作外部作用域的变量,常用于实现私有变量、模块化和高阶函数。私有变量示例展示了如何创建无法外部访问的计数器;模块化示例演示了封装私有变量和函数,防止全局污染;高阶函数示例则说明了如何使用闭包创建能接收或返回函数的函数。
15 2
|
1月前
|
存储 缓存 JavaScript
|
1月前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:理解其原理与实际应用
探索JavaScript中的闭包:理解其原理与实际应用
19 0
|
1天前
|
JavaScript 前端开发 UED
深入解析JavaScript原生操作DOM技术
【4月更文挑战第22天】本文深入探讨JavaScript原生DOM操作技术,包括使用`getElement*`方法和CSS选择器获取元素,借助`createElement`与`appendChild`动态创建及插入元素,修改元素内容、属性和样式,以及删除元素。通过掌握这些技术,开发者能实现页面动态交互,但应注意避免过度操作DOM以优化性能和用户体验。
|
1天前
|
JavaScript 前端开发 Linux
JavaScript 的跨平台特性
【4月更文挑战第22天】JavaScript 的跨平台特性
16 8
|
11天前
|
JavaScript 前端开发 API
框架分析(3)-Vue.js
框架分析(3)-Vue.js
|
21天前
|
人工智能 前端开发 JavaScript
【前端设计】HTML+CSS+JavaScript基本特性
【前端设计】HTML+CSS+JavaScript基本特性
|
27天前
|
JavaScript 前端开发 Java
深入剖析 JavaScript 闭包
深入探讨JavaScript闭包,了解其定义、特性、优缺点及作用。闭包是函数与其引用环境的组合,允许内层函数访问外层作用域,常驻内存可能导致内存泄露。优点包括创建私有变量,缺点则涉及内存使用。闭包在变量搜索中遵循从内到外的规则,并影响变量的作用域和生存周期。理解闭包有助于优化代码并避免性能问题。
21 1
|
1月前
|
监控 JavaScript 安全
监控内网电脑软件设计与实现:基于Node.js的服务器端架构分析
在当今信息技术高度发达的时代,监控内网电脑的需求日益增长。企业需要确保网络安全,个人用户也需要监控家庭网络以保护隐私和安全。本文将介绍一种基于Node.js的服务器端架构,用于设计和实现监控内网电脑软件。
99 0