<!DOCTYPE html>
<html>
<head>
<meta charset="GB2312">
<title></title>
</head>
<body>
<script>
//匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。
//通过表达式自我执行
/*(function box(){
alert('Lee');
})(); //()表示执行函数,并且传参*/
//个人理解,相当于Java语言的 (new object()).toString();
//函数里的匿名函数
/*function box(){
return function(){
return 'Brozer';
}
}
alert(box()());//个人理解,这里有点类似双重指针
alert(box);
alert(box());*/
// 使用闭包有一个优点,也是它的缺点:
// 就是可以把局部变量驻留在内存中,可以避免使 用全局变量。
// (全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,
// 所以推荐使用私有的,封装的局部变量)。
//通过全局变量来累加
/*var age=100;
function box(){
age++;
}
box();
alert(age);*/
//通过局部变量无法实现累加
/*function box(){
var age=100;
age++;
return age;
}
alert(box());
alert(box());//101,无法实现累加,因为又被初始化了*/
//通过闭包可以实现局部变量的累加
/*function box(){
var age=100;
return function(){
age++;
return age;
}
}
var b=box();
alert(b());
alert(b());*/
//作用域链的机制导致一个问题,在循环中里的匿名函数取得的任何变量都是最后一个 值。
/*function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=function(){
return i;
}
}
return arr;
}
var b=box();
alert(b.length);
for(var i=0;i<b.length;i++){
alert(b[i]());//输出的值都为5
}*/
// 上面的例子输出的结果都是 5,
// 也就是循环后得到的最大的 i 值。
// 因为 b[i]调用的是匿 名函数,匿名函数并没有自我执行,
// 等到调用的时候,box()已执行完毕,
// i 早已变成 5,所 以最终的结果就是 5 个 5。
//循环里包含匿名函数,自我执行匿名函数
/*function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=(function(num){ //自我执行
return num;
})(i);
}
return arr;
}
var b=box();
for(var i=0;i<b.length;i++){
alert(b[i]); //这里返回的是数组,直接打印即可
}
*/
// 我们让匿名函数进行自我执行,导致最终返回给 a[i]的是数组而不是函数了。
// 最终导致 b[0]-b[4]中保留了 0,1,2,3,4 的值
//循环里包含匿名函数,匿名函数下再做个匿名函数
/* function box(){
var arr=[];
for(var i=0;i<5;i++){
arr[i]=(function(num){
return function(){
return num;
}
})(i);
}
return arr;
}
var b=box();
for(var i=0;i<b.length;i++){
alert(b[i]());
}
*/
// 关于 this 对象 在闭包中使用 this 对象也可能会导致一些问题,
// this 对象是在运行时基于函数的执行环 境绑定的,
// 如果 this 在全局范围就是 window,如果在对象内部就指向这个对象。
// 而闭包却 在运行时指向 window 的,因为闭包并不属于这个对象的属性或方法。
/*var user='The Window';
var obj={
user:'The Object',
getUserFunction:function(){
return function(){ //闭包不属于obj,里面的this指向window
return this.user;
};
}
};
alert(obj.getUserFunction()());//The Window
//可以强制指向某个对象
alert(obj.getUserFunction().call(obj)); //The Object
*/
//模仿块级作用域
//JavaScript没有块级作用域的概念
/*function box(count){
for(var i=0;i<count;i++){}
alert(i); //i不会因为离开了for块就失效
}
box(2);
*/
/*function box(count){
for(var i=0;i<count;i++){}
var i;
alert(i);
}
box(2);*/
// 以上两个例子,说明 JavaScript 没有块级语句的作用域,
// if(){}for(){}等没有作用域, 如果有,出了这个范围 i 就应该被销毁了。
// 就算重新声明同一个变量也不会改变它的值。
// JavaScript 不会提醒你是否多次声明了同一个变量;
// 遇到这种情况,它只会对后续的声 明视而不见(如果初始化了,当然还会执行的)。
// 使用模仿块级作用域可避免这个问题。
//模仿块级作用域(私有作用域)
/*(function(){
//这里是块级作用域
})();
*/
//使用块级作用域改写
/*var i=19;
function Box(count){
var i=1;
(function(){
for(var i=0;i<count;i++){}
})();
alert(i);
}
box(2);
*/
//私有变量 JavaScript 没有私有属性的概念;
// 所有的对象属性都是公有的。不过,却有一个私有变 量的概念。
// 任何在函数中定义的变量,都可以认为是私有变量,
// 因为不能在函数的外部访问 这些变量。
// 而通过函数内部创建一个闭包,
// 那么闭包通过自己的作用域链也可以访问这些变量。
// 而 利用这一点,可以创建用于访问私有变量的公有方法。
function Box(){
var age=100;
function run(){
return '运行中...';
}
this.get=function(){
return age+run();
};
}
var box=new Box();
alert(box.get());
</script>
</body>
</html>
Javascript——匿名函数与闭包(操作指南)
最新推荐文章于 2024-03-25 11:38:17 发布