陕西建设监理协会网站,最受欢迎的公众号排行榜,比较好的国外网站建设公司,长沙关键词优化费用1、什么是闭包#xff1f;
闭包是指有权访问另一个函数作用域中的变量的函数#xff0c;创建闭包的最常见的方式就是在一个函数内创建另一个函数。 温馨提示#xff1a;由于闭包所在的作用域返回的局部变量不会被销毁#xff0c;所以会占用内存。过度的使用闭包会迫使性能…1、什么是闭包
闭包是指有权访问另一个函数作用域中的变量的函数创建闭包的最常见的方式就是在一个函数内创建另一个函数。 温馨提示由于闭包所在的作用域返回的局部变量不会被销毁所以会占用内存。过度的使用闭包会迫使性能下降因此建议大家在有必要的情况下再使用闭包。 闭包的官方解释 闭包closure是一个函数以及其捆绑的周边环境状态lexical environment词法环境的引用的组合。换而言之闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中闭包会随着函数的创建而被同时创建。 function fn(){var arr [];for(var i 0; i 3; i){arr.push(function(){return i;});}return arr;
}
var b fn();
for(var i 0; i b.length; i){console.log(b[i]());
}
这个控制台输出的是三个3你知道为什么嘛
答这是因为在第3行的这个for循环执行的过程当中每次都只是向数组中添加了一个匿名函数但是你要知道这个时候这些函数并没有自我执行。当你通过b[i]()调用匿名函数的时候通过闭包获得的i已经是3了所以每次输出的都是3。
那么如果你想得到0,1,2怎么办呢这个时候你就需要知道闭包怎么用了。
方法一闭包立即执行函数表达式
function fn(){var arr [];for(var i 0; i 3; i){arr.push((function(num){return function(){return num;};})(i));}return arr;
}
var b fn();
for(var i 0; i b.length; i){console.log(b[i]());
}
将立即执行函数表达式IIFE (function(num) { ... })(i) 包裹在 arr.push() 中这样可以在每次循环时创建一个新的作用域并传入当前的 i 值作为参数 num。这样内部的匿名函数就能够捕获并保存每次循环时的 i 值从而避免了之前出现的当匿名函数执行时i值已经变为3的问题。
通过匿名函数的立即执行将立即执行后返回的函数直接赋值给数组arr。每次循环即将i的值传递给num又因为num在函数中所以有自己的独立作用域因此num得到的值为每次循环传递进来的i值即012
方法二只是把闭包函数单独抽离出来了而已
function createClosure(num) {return function() {return num;};
}function fn() {var arr [];for (var i 0; i 3; i) {arr.push(createClosure(i));}return arr;
}var b fn();
for (var i 0; i b.length; i) {console.log(b[i]());
}
定义了一个 createClosure 函数它接受一个参数 num 并返回一个闭包函数该闭包函数可以访问并返回 num 的值。闭包可以帮助我们在每次循环中创建一个独立的作用域并保留每次循环中变量i的值。
在JavaScript中当内部函数引用了外部函数的变量时会创建一个闭包使得内部函数能够访问和保留外部函数作用域中的变量。这样每个内部函数都有自己的 num 变量它们分别对应每次循环中的 i 值避免了之前版本中由于共享同一个 i 变量导致的问题。
关于使用闭包时的this指向问题
var color red;
function fn(){return this.color;
}
var obj {color:yellow,fn:function(){return function(){//返回匿名函数return this.color;}}
}
console.log(fn());//red 在外部直接调用this为window
var b obj.fn();//b为window下的变量,获得的值为obj对象下的fn方法返回的匿名函数
console.log(b());//red 因为是在window环境下运行所以this指缶的是window
//可以通过call或apply改变函数内的this指向
console.log(b.call(obj));//yellow
console.log(b.apply(obj));//yellow
console.log(fn.call(obj));//yellow//或者这个保存对当前对象的引用
var color red;
function fn(){return this.color;
}
var obj {color: yellow,fn: function(){var self this; // 保存对当前对象的引用return function(){return self.color; // 使用保存的引用来访问对象的color属性}}
}
var b obj.fn();
console.log(b()); // 输出 yellow
总结
闭包解决了以下两个问题
1. 可以读取函数内部的变量
2. 让这些变量的值始终保持在内存中。不会在函数调用后被清除
但同时闭包也有它的缺点
1. 由于闭包会使得函数中的变量都被保存到内存中,滥用闭包很容易造成内存消耗过大,导致网页性能问题。解决方法是在退出函数之前将不再使用的局部变量全部删除。 闭包会导致内存泄漏。内存泄漏指的是在程序中不再需要使用的内存没有被释放或回收的情况。当程序中的对象在不再需要时仍然占用内存空间而没有被垃圾回收机制释放就会导致内存泄漏问题。造成内存泄漏的情况可能有定时器未清理闭包对象相互引用等。 我们在使用闭包时需要特别注意内存泄漏的问题可以用以下两种方法解决内存泄露问题 1.及时释放闭包手动调用闭包函数并将其返回值赋值为null这样可以让闭包中的变量及时被垃圾回收器回收。 2.使用立即执行函数在创建闭包时将需要保留的变量传递给一个立即执行函数并将这些变量作为参数传递给闭包函数这样可以保留所需的变量而不会导致其他变量的内存泄漏。 2. 闭包可以使得函数内部的值可以在函数外部进行修改。所以如果你把父函数当作对象(object)使用把闭包当作它的公用方法(Public Method)把内部变量当作它的私有属性(private value)这时一定要小心不要随便改变父函数内部变量的值。