闭包函数条件:
// 1 在函数A内部返回函数B
// 2 在函数B中访问函数A的私有作用域变量intNum
// 3 在函数A外部,有变量引用函数B(调用函数A,执行结果就是函数B,引用f1,实际上就是引用函数B)
function A(){
var intNum = 100;
return function B(){
var num = intNum;
return num
}
}
let f1 = A(); // 发f1变量接收函数A的返回值
let f2 = f1()
闭包特点:
1 函数执行空间不销毁‘
优点:变量不会销毁,演唱变量的生命周期;
缺点:一直占用内存
2 在函数外部访问函数内部的变量
优点:在函数外部访问函数内部的变量
缺点:时刻保持引用,导致函数执行空间一直不销毁
3 保护私有变量
优点:不会污染全局环境
缺点:访问不方便
闭包使用:
let btns = document.querySelectorAll('button')
// 问题:点击每个按钮输出都是5
// 1 用let定义循环变量i可避免这种情况;
for(var i = 0; i<btns.length; i++){
btns[i].onclick = function(){
console.log(i); // 变量i用var定义,点击每个按钮输出都是5;用let定义可避免这种情况
}
}
// 2 使用闭包;
for(var i=0; i<btns.length; i++){
function fn(a){
return function(){
console.log(a);
}
}
btns[i].onclick = fn(i)
}
闭包变换写法1
// 闭包变换写法1
// btns[i].onclick外部函数接收fn的内部函数
for(var i=0; i<btns.length; i++){
function fn(a){
btns[a].onclick = function(){
console.log(a);
}
}
fn(i)
}
闭包变换写法2
// 闭包变换写法2
function fn(a){
btns[a].onclick = function(){
console.log(a);
}
}
for(var i=0; i<btns.length; i++){
fn(i)
}
闭包练习:
练习1:通过闭包,函数f改变函数g的返回值
(function(){
var m = 0; // m100
function getM(){
return m
}
function setA(val){
m = val;
}
window.g = getM;
window.f = setA;
})()
f(100);
console.log(g()); // 100
练习2
function fun(n,m){
console.log(m);
return{
fun:function(k){
return fun(k,n)
}
};
}
var a = fun(0); //undefined fun()函数返回的值是一个对象,变量接收
a.fun(1); // 0
a.fun(2); // 0
a.fun(3); // 0
var b = fun(0).fun(1).fun(2).fun(3) // undefined 0 1 2 3
var c = fun(0).fun(1); c.fun(2); c.fun(3) // undefined 0 1 1