javascript匿名函数和闭包

匿名函数:没有名称的函数;

闭包:可以在函数作用域中访问变量的函数;

一个匿名函数


公共函数
函数(box){函数名是框;
return'lee;
}
框(=李);调用函数;
匿名函数
(函数){匿名函数,错误;
return'lee;
}
自我执行的表达式
(函数(名称){)
console.log(名称); / / = >李;
}();()执行函数,并可以传递参数;
将分配给变量的匿名函数
Var(Box =函数)分配给变量的匿名函数;
return'lee;
};
Console.log((箱); / /电话)模式和类似的函数调用;
中的匿名函数
函数框(){
返回函数(name)在匿名函数中的函数,生成闭包;
返回的名称;
};
};
Console.log((盒)(李)); / /盒(匿名)函数的函数调用,并通过;


两封

闭包:在另一个函数域中有权访问变量的函数;

创建闭包的常用方法是在一个函数中创建另一个函数,通过另一个函数访问函数的局部变量;


局部变量的关闭可以返回
函数框(){
无功用户= 'lee;
函数返回本地变量的框(用户);
返回用户;
};
}
console.log(箱)(()); / / = >李;直接呼叫()()来获取一个匿名函数的返回值;

var(=);
Console.log((b)); / / = >李;另一个称为匿名函数;

优点:可以将本地变量放在内存中,可以避免使用全局变量;
(全局变量污染导致应用程序不可预测性,每个模块都可以调用将导致灾难;建议使用私有、局部变量包);



/缺点:
通过全局变量累积
var年龄= 100;全局变量;
函数框(){
年龄+ +;模块级可以称为全局变量,累计;
};
(方框);执行函数,添加一个;
console.log(年龄); / / = > 101;全局变量的输出;
(方框);执行函数,添加一个;
console.log(年龄); / / = > 102;全局变量的输出;
通过本地变量实现累积的
函数框(){
var年龄= 100;
年龄+ +;
返回的年龄;
}
Console.log((盒)); / / = > 101;
Console.log((盒)); / / = > 101;累计实现二次,因为当调用函数时函数内部的变量年龄已初始化;

累积闭包可以通过本地变量实现。
函数框(){
var年龄= 100;
函数返回(函数)以实现累积;
年龄+;
返回年龄;返回和累积变量;
此时(框)};局部变量年龄函数值已被修改为累计值;
}
var(b);分配给变量的框()函数;
Console.log((b)); / / = > 101;匿名函数调用,累积;
Console.log((b)); / / = > 102;第二调用匿名函数,高达2倍;

本地变量:资源不会被关闭范围立即返回,破坏恢复,它可能占用更多内存;因此过度使用闭包将导致性能下降;(在私有域中引用的闭包实现变量破坏)
作用域链的机制会导致一个问题,循环中匿名函数中的任何变量都是最后一个值;



循环包含一个匿名函数。
函数框(){
var arr = { };
对于(var i = 0;i < 5;i +);当声明变量i = 5,循环停止;循环变量在i = 5;
ARR {我} =功能(ARR {我}){ / /得到的是没有执行匿名函数(函数){ };
还我;
};
};
报酬; / / ARR = {函数,函数,函数,函数,函数};
}
var =箱(B); / / = > {函数,函数,函数,函数,函数};箱()函数返回一个数组的数组;
console.log(b.length); / / = > 5;得到的功能设置数组的长度;
对于(var i = 0;i < b.length;i++){
console.log(箱)({ }()); / / = > 5,5,5,5,5;每个函数值的输出是最后的价值;
}
上面的示例输出是5,我是循环后获得的最大值;
因为这个函数被称为匿名函数,所以匿名函数不会自动执行,直到调用的时间(框)被执行时,我已经变成了5;

循环包含一个匿名函数 - 1,自动执行匿名函数。
函数框(){
var arr = { };
对于(var i = 0;i < 5;i + +){
ARR {我} =(function(Num){ / / ARR {我}是一个匿名函数的数值0-4的结果实施后;
返回num;
})(i);自执行和传输参数;
}
报酬;
}
var =箱(B); / / = > { 0,1,2,3,4 };代表箱B()返回一个数组;
对于(var i = 0;i < b.length;i++){
console.log(B {我}); / / 01234;这里是数值返回;
};
/ /例子,我们让匿名函数是自我执行,导致一个{我}最后的回归是一个数组,而不是功能;最终导致B { 0 } B { 4 }保留值0,1,2,3,4;

循环包含一个匿名函数 - 2,匿名函数执行匿名函数;
函数框(){
var arr = { };
对于(var i = 0;i < 5;i + +){
ARR {我} =(function(NUM){)
返回(函数)返回函数;
返回num;
}
})(一);
}
报酬; / / ARR = {函数,函数,函数,函数,函数};
}
var(=);
对于(var i = 0;i < b.length;i++){
Console.log((B {我})); / / 0,1,2,3,4;
};

1 / / 2,我们通过匿名函数自我执行,分配给ARR {我}立即;
每一个调用都是通过值传递的,所以最终的返回值是通过增加i来指定的,而不是变量i中的Box()函数;


三这个对象




使用闭包中的这个对象可能会导致一些问题;这个对象是基于运行时执行环境绑定函数的;
如果这个全局范围指向窗口,如果对象指向对象内部;
但是在运行时和窗口关闭时,因为闭包的属性或方法不属于这个对象;
无功用户=;
var obj = { {
用户:'object,
getuserfunction:函数(){
返回(功能){ / /关闭不属于对象,里面的这个窗口;
返回this.user;
};
}
};
console.log(obj。getuserfunction)(()); / / = >窗口;

可以强制对象
console.log(obj。getuserfunction)。叫((obj)); / / = >对象;

可以从对象域的角色中提取
getuserfunction:函数(){
var = / /本;从对象的方法;在对目标对象的指针;
返回函数(){
返回that.user;
}
}
console.log(obj。getuserfunction)(()); / / = >对象;


四内存泄漏




因为不同的垃圾收集方式即 / / Jscript对象和DOM对象,所以在伊江的关闭将导致内存泄漏的问题,而不能在存储器元件的破坏;
函数框(){
无功odiv = document.getelementbyid('odiv '); / / odiv后一直驻留在内存;
odiv.onclick =函数(){
警报(odiv .innerHTML); / /这里有内存泄漏odiv;
};
odiv = null; / /引用;
}
(盒);
由于匿名函数 / /保存箱()指的是活跃的对象,从而导致减少odiv参考数;
只要 / /匿名函数的存在,引用计数至少1 odiv;因此,它所占用的内存将不会恢复;
如果不使用电梯引用,那么在发布之前请等待浏览器关闭;


五模拟块级作用域(立即定义和调用匿名函数)




没有块级范围的概念;
这意味着,在变量定义中,在(if语句)中,实际上包含的是函数而不是创建语句;
函数框(计数){
对于(var i = 0;i = 2;i = 2个循环停止,此时i = 2;
console.log(我); / / = > 2我;不是因为失败左块;
}
框(2);

函数框(计数){
对于(var i = 0;i <计数;i + +){ }
var i;
console.log(我);
}
框(2);
在Javascript中,变量i在框()中定义为对象的活动,因此它必须从定义开始,您可以在函数的任何地方访问它;
上面的两个示例说明了Javascript块级别no语句的范围,如果({ for for for)){ }(无作用域);
/ /如果作用域,在我被破坏的范围;

Javascript不会提醒重复语句是否相同的变量;在这种情况下,它只对后续语句(如果初始化和赋值或执行)视而不见;

模拟块级别作用域(私有作用域)
(函数(){())
这里是块级作用域;
});
上面的代码定义并立即调用一个匿名函数;一对括号中的函数声明,表示它实际上是一个函数表达式;

/块级作用域(私有范围)重写
函数框(计数){
(函数(){())
对于(var i = 0;i <计数;i + +){ }
});
console.log(我); / /错误,无法访问私有;变我之范围内,私人的范围被破坏。
}
框(2);
使用块级别作用域,任何变量定义的匿名函数将在执行结束时被销毁;(我只能在循环中使用,在销毁后使用);
和访问私有变量计数的范围,因为这个匿名函数是一个闭包,他可以访问包含在;
这一技术通常在全局范围内用于外部函数,从而限制了全局范围来添加太多变量和函数;
在一般情况下,我们应该尽可能少地将变量和函数添加到全局范围;全局变量和函数更容易导致命名冲突;
/块级别作用域,每个开发人员可以使用自己的变量,而不必担心搅乱全局范围;
(函数(){())
var = {三}箱;
console.log(箱); / / = > {三};箱是不知道;
}());匿名函数变量的销毁;
console.log(箱); / / = >箱没有定义;
内存问题:全局范围中的块级别范围可以减少对闭包的占用,因为没有引用匿名函数。
如果功能完成,您可以立即销毁范围链;


六私有变量




私有财产的无用概念;所有属性都是通用的;
但是,在变量的任何函数中都定义了私有变量的概念,可以将其视为私有变量,因为它们不能在外部函数中访问这些变量;
私有变量,包括函数/局部变量的函数以及函数内部定义的其他函数;
函数框(){
var年龄= 100;无法访问外部的私有变量;
}

通过内部创建一个闭包,然后通过范围链的闭包自己也可以访问这些变量;
使用此点,可以创建访问私有变量的公共方法;特权方法;
函数(box){构造函数;
var年龄= 100; /私有变量;
函数(运行);
返回'运行';
};
(this.get =功能){ / /公共权限的方法;
返回(年龄+运行);将被分配给变量;
};
}
var框=新框();
console.log(box.get());

可以通过构造方法参数来访问私有变量
功能人(名称){
var用户名=;这个句子实际上可以省略;
this.getuser =函数(){
返回用户;
};
this.setuser =函数(名){
用户名;
}
}
var p =新的人('lee);
Console.log((p.getuser)); / / = >李;
console.log(p.setuser(杰克));
Console.log((p.getuser)); / / = >杰克;
但是,对于每个实例的模型构造函数的缺点也将创建一组新的方法;而使用静态私有变量来实现特权方法可以避免这个问题;


七个静态私有变量




在私有变量或函数定义中的块级范围(私有范围),也可以创建外部公共特权方法;
(函数())创建私有范围;
var年龄= 100;静态私有变量;
函数运行(){
返回'运行';
};
框=函数(){ };使用函数表达式定义构造函数;
(Box.prototype。=函数)原型方法中定义的公共/特权(特权);
返回年龄+跑();
};
});
var框=新框();
console.log(箱)(100); / /操作…;
上述声明/对象,采用盒(功能)=功能(箱){ } { }来代替;不在盒子里使用var关键字声明
结果:没有声明变量的初始化,总是创建一个全局变量;因此,框是一个全局变量,可以在私有范围之外访问;
因为如果函数声明构造函数的定义,它变成了一个私有函数,而不是在全局访问中,所以你要使用函数类型构造函数定义;
(函数(){())
var用户;
在这里定义的函数=值是一个全局变量;
用户=值;在这里访问私有变量名称构造函数;
};
person.prototype.getuser =函数(){
返回用户;
};
person.prototype.setuser =函数(值){
用户=值;
}
});
var =新人();
Person.setUser('lee);
Console.log((人。getUser)); / / = >李;
使用原型方法进行共享,而用户将成为静态属性;
所谓的静态属性:在共享中对不同对象的属性;


八模块模式




简而言之,如果您必须创建一个对象并用一些数据初始化它,但也要对这些私有数据进行一些公共访问,那么您可以使用模块模式;
在构造函数中用于创建私有变量和特权方法之前;
然后创建创建模块模式的对象文本方式;
var对象是一个单例对象:只有一个对象实例;
这是年龄:100公共属性,将被转换为私有;
运行:函数(){
返回'运行';
};
};

模块化模型/变量和函数的私有化:
var函数(){()
var年龄= 100;
函数运行(){
返回'运行';
}
作为返回值的函数返回一个文本对象;
函数()返回对象字面值只能包含公共属性和方法;
返回(年龄+运行);因为这个对象是在匿名函数中定义的,所以它有权使用公共方法访问私有变量和函数;
}
基本上,这个对象文字定义是单个案例的公共接口;
(});
在这种模式下需要一些初始化的单例,也需要维护私有变量是非常有用的;

直接返回对象上面的例子,也可以写:
var函数(){()
var年龄= 100;
函数运行(){
返回'运行';
}
var obj = { / /创建文本对象;
函数(){
返回年龄+跑();
}
};
返回对象; / /返回新创建的对象;
(});

实际上在设计模式中的文字对象可以被视为一个单例模型;
所谓的单例模式,就是只保留对象的一个实例;

增强的模块模式:适合返回自定义对象或构造函数;
函数(台){ };
var函数(){()
var年龄= 100;
函数运行(){
返回'运行';
};
新办公桌();
书桌。=函数(){
返回年龄+跑();
};
回台;
(});
Console.log((盒)); / / = > 100操作;


九总结

在Javascript编程中,函数表达式是一种非常有用的技术;函数表达式可以不使用函数命名,从而实现动态编程。

1。函数表达式

函数表达式不同于函数声明;函数声明需要名称,但函数表达式不需要它;

没有名称的函数表达式称为匿名函数;2。关闭

当函数中定义了其他函数时,就会创建一个闭包。闭包有权访问函数内部的所有变量:

在后台执行环境中,闭包链包含它自己的作用域、函数作用域和全局范围。

通常,函数和所有变量的作用域在函数执行后被销毁。

但是,当函数返回一个闭包时,函数的作用域将保持在内存中,直到闭包不存在为止;3。块范围。

闭包的使用可以模拟Javascript中的块级范围(Javascript本身没有块级别范围)的概念,主要内容如下:

立即创建并调用函数,这样代码就可以执行,而对函数的引用也不会留在内存中;

结果是函数中的所有变量都会立即被销毁,除非一些变量被赋值给包含范围(外部范围)的变量,4。私有变量。

闭包也可以用于创建对象中的私有变量,如下所示:

虽然Javascript中没有私有对象属性的真正概念,但是闭包可以用来实现公共方法,公共方式可以访问范围内定义的变量。

您可以使用构造函数模式、原型模式来实现自定义类型的特权方法,而模块模式可以用来实现单例的特权方法。