时间:2021-05-26
本文实例讲述了javascript中的闭包概念与用法。分享给大家供大家参考,具体如下:
闭包的概念:闭包是指有权访问另一个函数作用域中的变量的函数 (引自《javascript高级程序设计第三版》178页)。闭包的优点是不会产生全局变量,避免变量污染问题,但是闭包也有一个缺点就是闭包携带包含它的函数作用域会比其它函数占用更多的内存,过度使用会导致内存占用过多。
wiki上关于闭包的概念:
In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions. Operationally, a closure is a record storing a function[a] together with an environment:[1] a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.[b] A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
简单来说:闭包是一个存储了函数以及与这个函数相关的环境信息的记录。
闭包实践一:初次体验闭包
function a() { var temp = 100; function b() { console.log(++temp); } return b;}var fn = a(); // 此时fn属于全局的函数。fn();// 101fn();// 102在函数a的内部return出了一个局部函数b。让函数fn接收函数a的返回值,也就是函数b。连续执行了两次fn,输出结果101,,102表示,函数fn一直引用着函数a中的局部变量temp。每次调用fn,temp都会被自增1。从此处说明了函数a一直没有被垃圾回收机制(GC)回收。以上代码还可以这样优化:
function a() { var temp = 100; return function() { console.log(++temp); }}var fn = a();a = null;fn();// 101fn();// 102fn = null; // 调用完毕后要,要解除对内部匿名函数的引用,以便释放内存闭包实践二:闭包与变量
分析下面的代码
html结构:
<ul> <li>0</li> <li>1</li> <li>2</li></ul>javascript结构:
var ul = document.querySelector('ul');// 为了演示方便,直接用html5的apivar lis = ul.children;for(var i=0; i< lis.length; i++) { lis[i].οnclick=function(){ console.log(i); }}当点击每个li时,输出的全都是3,在点击事件之前,for循环早已经执行完了,i的值为3。为了防止这种情况发生,for循环还可以修改成这样:
for(var i=0; i< lis.length; i++) { lis[i].οnclick=function(num){ return function(){ console.log(num); } }(i)}由于函数是按值传递的,所以就会将变量i的当前值赋给num,而在函数内部又返回了一个访问num的闭包。这样每次i的值就保存下来了。值得一提的是在ECMAScript6中可以用严格模式下用let 来声明i。这样可以直接保存i,有关es6,以后再深入学习,示例代码如下:
javascript结构:
'use strict'let ul = document.querySelector('ul');let lis = ul.children;for(let i=0; i< lis.length; i++) { lis[i].οnclick=function(){ console.log(i); }}闭包实践三:对实践二的深层剖析,闭包保存的是整个变量对象,而不是某个特殊的变量。(出自 《javascript高级程序设计第三版》 181页)
function createFunctions() { var result = new Array(); for(var i=0; i<10;i++) { result[i] = function() { return i; } } return result;}var arr = createFunctions();// 我们拿到并输出第一个数组元素函数的返回值var fn0 = arr[0];var varible0 = fn0();console.log(varible0); // 返回的是 10// 我们拿到并输出第二个数组元素函数的返回值var fn1 = arr[1];var varible1 = fn1();console.log(varible1); // 返回的是 10// 可见闭包保存的是这个变量i对象,i的最终结果是10我们只要对代码稍稍优化,用自执行函数来处理,就可以达到我们的预期了,如下:
function createFunctions() { var result = new Array(); for(var i=0; i<10;i++) { result[i] = (function(num) { return function(){ return num; } })(i) } return result;}var arr = createFunctions();// 我们拿到并输出第一个数组元素函数的返回值var fn0 = arr[0];var varible0 = fn0();console.log(varible0); // 返回的是 0// 我们拿到并输出最后一个数组元素函数的返回值var fn9 = arr[9];var varible9 = fn9();console.log(varible9); // 返回的是 9闭包实践四:闭包与this 使用不同的编程方式使用闭包,this指向不同的对象
var color = 'black';var person = { color:"yellow", getColorFun1:function(){ return function(){ return this.color; } }, getColorFun2:function(){ var that = this; return that.color; }}console.log(person.getColorFun1()()); // 指向了 black (备注:fn()()这种写法只限于非严格模式下)console.log(person.getColorFun2()); // 指向了yellow说明:当调用到person.getColorFun1()的时候,在全局变量中生成一个函数function(){return this.color},此时的this指向是window,所以执行到person.getColorFun1()()的时候,color为window对象下的变量color为black
而在person.getColorFun2函数中用that保存了当前对象person,而在闭包函数里面return出去的color是person的color,所以执行完person.getColorFun2()()的时,color是yellow。
实践四:闭包的高级应用
示例1:实现函数节流
window.onresize = throttle(function(){ var width = window.innerWidth || document.documentElement.clientWidth; console.log(width);},300); // 调节浏览器窗口,在松手后的0.3s后执行function throttle(fn,delay) { var timer = null; return function() { clearTimeout(timer); timer = setTimeout(fn,delay); }}示例2:实现封装对象
var Person = (function(){ var haha = 0; // 这里表示可以定义一能够使用到的参数 return function(name, age){ ++ haha; // 这里表示去使用定义到的参数,虽然在此处并没有实际意义。 this.name = name; this.age = age; };})();Person.prototype = { say : function(){ console.log(this.name + ' say hi'); }}var p1 = new Person('zhang san', 10);var p2 = new Person('li si', 20);console.log(p1.name); // zhang sanp1.say(); // zhang san say hip2.say(); // li si say hi感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例分析了Javascript闭包的概念及用法。分享给大家供大家参考。具体如下:提到闭包,想必大家都早有耳闻,下面说下我的简单理解。说实话平时工作中实际手动
本文实例分析了PHP程序设计中闭包的概念机用法,分享给大家供大家参考。具体分析如下:通常来说,闭包也就是PHP的匿名函数,但是和函数不同的是,闭包可以通过use
一般来说闭包这个概念在很多语言中都有涉及,本文主要谈谈python中的闭包定义及相关用法。Python中使用闭包主要是在进行函数式开发时使用。详情分析如下:一、
Javascript闭包闭包,是Javascript比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,
但javascript中并没有类概念,所谓的类也是模拟而来,通过函数加闭包模拟出类成员及私有成员(关于闭包可以参见跨越边界:闭包)。这里我们将用比较平实的方式来