# 闭包的实质
闭包,就是能够读取其他函数内部变量的函数
# 闭包的产生条件
- 函数嵌套
- 内部函数调用外部函数变量
- 执行外部函数
# 闭包的特性
(你对闭包的理解)
- 延长局部变量的生命周期:闭包调用的外部函数变量会一直存活,直到闭包释放。这容易造成内存泄漏。
- 突破作用域限制:函数外部可以操作函数内部的变量。
- 使用闭包主要是为了设置私有的变量和方法,避免污染全局变量,可以完成一些功能模块的封装,以及实现数据缓存效果。
# 闭包的生命周期
- 产生:执行内部函数的定义时,产生闭包
- 死亡:内部函数成为垃圾对象时(赋值null)
# 说说作用域链
javascript中,有函数即形成作用域,有函数嵌套那就形成了一条作用域链,作用域链向上可以一直访问到global对象,向下则不允许访问。
# 闭包的几种形式
(一)将函数作为另一个函数的返回值
function a() {
var x = 2;
function b() {
x++;
console.log(x);
}
return b;
}
var f = a();
f();
f();
(二)将函数作为实参,传递给另一个函数调用
function showMsg(msg,time){
setTimeout(function(){
alert(msg);
},time);
}
showMsg('helloWorld',1000);
# 闭包的应用
实现JS模块
- 具有特定功能的js文件
- 将所有的数据和功能都封装在一个函数内部(私有的)
- 只向外暴露一个包含n个方法的对象或函数
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
(function(window){
var name;
var age;
function setName(n){
name = n;
}
function getName(){
return name;
}
function setAge(x){
age = x;
}
function getAge(){
return age;
}
return window.mo = {
setName:setName,
getName:getName,
setAge:setAge,
getAge:getAge
}
})(window);
# 面试题
(一)
var name = "the Window";
var object = {
name : "My object",
getNameFunc : function(){
return function(){
return this.name;
}
}
};
console.log(object.getNameFunc()());
//输出:the Window
(二)
var name = "the Window";
var object = {
name : "My object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
}
}
};
console.log(object.getNameFunc()());
//输出:My object
(三)
function fun(n, o) {
console.log(o);
return {
fun: function (m) {
return fun(m, n);
},
};
}
var a = fun(0); //undefined { fun : function(m){ n=0; return fun(m,n)}}
a.fun(1); // 0
a.fun(2); // 0
a.fun(3); // 0
var b = fun(0).fun(1).fun(2).fun(3);
//undefined { fun : function(m){ n=0; return fun(m,n)}}
//0 { fun : function(m){ n=1; return fun(m,n)}}
//1 { fun : function(m){ n=2; return fun(m,n)}}
//2 { fun : function(m){ n=3; return fun(m,n)}}
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);
// undefined 0 1 1