Js基础知识6-JavaScript匿名函数和闭包
匿名函数
1,把匿名函数赋值给变量
var test = function() {
return 'guoyu';
};
alert(test);//test是个函数
alert(test());
2,把匿名函数自我执行的返回值赋值给变量
var test = (function() {
return 'GY';
})();
alert(test);//弹出 GY
3,自我执行,第一个圆括号放匿名函数,第二个括号执行并传参
(function(a, b) {
alert(a+b);
})(2,5);//直接弹出7
4,自我执匿名函数的传参
alert((function() {
return 'guoyu';
})());
5,函数里面放一个匿名函数
functiontest() {
return function() {
return 'guoyu';
};
}
alert(test());//执行test(),结果是一个函数体
alert(test()());//弹出guoyu
var t = test();
alert(t());//弹出guoyu
闭包
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
1,通过闭包可以返回局部变量
functiontest() {
var age = 28;
return function() {
return age;
};
}
alert(test()());//直接弹出 28
2,使用闭包有个优点,同时也是缺点:局部变量驻留内存中,可以避免使用全局变量(全局变量污染导致应用程序的不可预知性,每个模块都可以调用必将引来灾难,推荐使用私有的,封装的局部变量)
使用全局变量进行累加
var age = 20;
functiontest() {
age++;
return age;
}
alert(test());//21
alert(test());//22
如果你把var age = 20;放进test()函数内,那么每次执行都会重新初始化为20,每次弹出的都是21,无论执行多少次!
3,使用匿名函数实现局部变量驻留内存中从而累加
functiontest() {
var age = 20;
return function() {
age++;
return age;
}
}
var t = test();
alert(t());//21
alert(t());//22
alert(t());//23
alert(t());//24
/*如果每次都初始化age = 20;那么每次返回都是21,不能实现累加,因此要避免初始化那一句,只要调用第一个return 语句即可,每次只调用t()即可*/
t = null;//解除引用,等待垃圾回收
循环里的匿名函数的取值问题
function test() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function() {
return i;
};
}
//循环执行完毕,i最终是4++,就是5
return arr;
}
/*
alert(test());
打印出5个并列的“function() {return i;}”,
因为arr数组的每个元素都是一个匿名函数,每个匿名函数都是返回"i",
并不是返回1,2,3....,因为这个匿名函数是死的,没有执行(自执行)
*/
alert(test()[0]);//弹出“function() {return i;}”
var t = test();
for (var i = 0; i < 5; i++) {
//alert(t[i]);//数组里面都是一个没有自执行的匿名函数
//现在让数组里的每个死函数执行起来,但是全都是弹出‘5’
//因为执行test()里的循环后,i已经为5了,但每个数组里面都存的是个死函数,返回一个死i
alert(t[i]());
}
如何解决上述的问题呢?
修改1
functiontest() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = i;//这里不用匿名函数,直接给个i,
}
return arr;
}
var t = test();
for (var i = 0; i < 5; i++) {
alert(t[i]);//依次弹出0,1,2,3,4
}
修改2,通过自我即时执行匿名函数:
//将匿名函数里面的变量驻留到内存感觉像全局变量
functiontest() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = (function(num) {
return num;
})(i);
}
return arr;
}
var t = test();
for (var i = 0; i < 5; i++) {
alert(t[i]);//依次弹出0,1,2,3,4
}
修改3:
functiontest() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = (function(num) {
//return num;
return function() {//这么写就是闭包了,闭包将变量驻留在内存,和前例中累加一个道理
return num;
};
})(i);
}
return arr;
}
var t = test();
for (var i = 0; i < 5; i++) {
//alert(t[i]);这里返回的是5个依次“function() {return num;}”
alert(t[i]());//依次打印出0,1,2,3,4
}
闭包中的this
var test = {
getThis: function() {
return this;
}
};
alert(test.getThis());//[object Object]
再看看闭包中:
var test = {
getThis: function() {
return function() {//这么写就是闭包了
return this;
};
}
};
alert(test.getThis()());//[object Window]
结论:this 对象在运行时基于函数的执行环境绑定的,如果this在全局范围就是widow,如果在对象内部就指向这个对象。而闭包在运行时指向window的,因为闭包不属于这个对象的属性或方法,再看下面
var user = 'The Window';
var box = {
user:'The Box',
getUser: function() {
//return this.user;
return function() {//这么写就是闭包了
return this.user;
};
}
};
alert(box.getUser()());//The Window
那么有的同学想问了,怎么才能让它弹出 The box呢?
方法有两个:对象冒充,变量保存_this
var user = 'The Window';
var box = {
user:'The Box',
getUser: function() {//这个地方要冒充一下
return function() {
return this.user;
};
}
};
alert(box.getUser().call(box));//The Box
var user = 'The Window';
var box = {
user:'The Box',
getUser: function() {
var _this = this;//保存到临时变量
return function() {
return _this.user;
};
}
};
alert(box.getUser()());//The Box
模仿块级作用域,for ,if 等块级里的东西封装起来,变量私有化,可以保护数据,防止泄露,js没有私有作用域这个概念
functiontest() {
for(var i = 0; i < 5; i++) {//块级作用域,可惜JS没这个东西
}
var i;//重新声明也不影响
alert(i);//即使超出for块级,依旧打印出5,说明js没有块级作用域这个概念
}
test();
开始使用块级作用域,也就是出了if , for等块,里面的i就不再起效,方法就是包含自我执行的匿名函数,就可以实现私有作用域
functiontest() {
(function() {
for (var i = 0; i < 5; i++) {//包含自我执行的匿名函数,就可以实现私有作用域
alert(i);
}
})();
alert(i);
//这里i就不认识了,相当于没定义i,i被销毁了,后面继续定义i和上面的i没任何关系,防止污染
}
test();
(function() {
var age = 20;
alert(age);
})();
alert(age);//报错,undefined
//这样可以全局变量私有化,防止污染
私有变量(外部不可访问)
functiontest() {
var age = 20; //私有变量
}
functionTest() {
this.age = 20;//属性:公有的,外部可访问
this.run = function() {//方法:公有的
return 'is running...';
};
}
var t = new Test();
alert(t.age);
alert(t.run());
functionTest() {
var age = 20; //私有变量
functionrun() {//私有函数
return ' is running...';
}
this.publicGo = function() { //对外可见的公共接口,特权方法
return age + run();
};
}
var t = new Test();
alert(t.publicGo());
//20 is running...私有变量,私有函数,通过公共接口被访问
//把一些细节封装起来,通过一些接口去访问
Js基础知识6-JavaScript匿名函数和闭包的更多相关文章
- 第一百一十节,JavaScript匿名函数和闭包
JavaScript匿名函数和闭包 学习要点: 1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数.声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂 ...
- [从jQuery看JavaScript]-匿名函数与闭包(Anonymous Function and Closure)【转】
(function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我就迷糊了.为什么只有 ...
- 深入理解javascript 匿名函数和闭包
代码如下: (function(){ //这里忽略jQuery所有实现 })(); (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其 ...
- [从jQuery看JavaScript]-匿名函数与闭包
jQuery片段: (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的第一眼,我 ...
- javascript 匿名函数及闭包----转载
网上很多解释,我无法理解,我想知道原理...这篇文章应该可以透彻一点Query片段:view plaincopy to clipboardprint? (function(){ //这里忽略 ...
- [从jQuery看JavaScript]-匿名函数与闭包(Anonymous Function and Closure)
http://blog.csdn.net/natineprince/article/details/4759533 jQuery片段: (function(){ //这里忽略jQuery所有实现 ...
- 详谈JavaScript 匿名函数及闭包
1.匿名函数函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种:这 ...
- javascript匿名函数及闭包深入理解及应用
1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种: ...
- 浅谈JavaScript匿名函数与闭包
一. 匿名函数 //普通函数定义: //单独的匿名函数是无法运行的.就算运行了,也无法调用,因为没有名称. 如: function(){ alert('123'); ...
- Javascript 匿名函数与闭包
请见如下一个闭包示例: color = "red"; var obj = { color: "blue", getColor: function () { fu ...
随机推荐
- iOS - 集成Bundle资源文件包
1.Bundle 文件 Bundle 文件,简单理解,就是资源文件包.我们将许多图片.XIB.文本文件组织在一起,打包成一个 Bundle 文件.方便在其他项目中引用包内的资源. Bundle 文件是 ...
- python---不支持中文注释解决办法
很神奇的一件事儿,pycharm不支持中文注释,具体解决办法: #-*- coding: utf- -*- 具体使用:
- HDU 6441 - Find Integer - [费马大定理][2018CCPC网络选拔赛第4题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6441 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- MYSQL 命令行显示乱码 解决方案
中文乱码是因为编码集不支持,所以要改变编码 先查看下设置的编码 使用如下命令 show variables like 'character%'; 在 mysql.conf (Ubuntu mysql5 ...
- 洛谷P5021 赛道修建 NOIp2018 贪心+二分答案
正解:贪心+LCA+二分答案 解题报告: 想先港下部分分qwq因为我部分分只拿到了10ptsQAQ(时间不够不是理由,其实还是太弱,所以要想很久,所以才时间不够QAQ m=1 找直径长度,完 一条链 ...
- MySQL如何开启慢查询
一 简介 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能. 二 参数说明 slow_query_log 慢查询开启状态 slo ...
- Linux文件目录介绍及文件颜色区别
文件颜色代表含义: 蓝色表示目录: 绿色表示可执行文件: 红色表示压缩文件: 浅蓝色表示链接文件: 白色表示其他文件: 黄色是设备文件,包括block, char, fifo. 常见目录解释 Linu ...
- OC convertRect
举个例子: redView = [[UIView alloc]initWithFrame:CGRectMake(50, 100, 100, 100)]; redView.backgroundColor ...
- 12 jmeter性能测试实战--web程序
项目背景 项目:XX网站环境:Windows需求:并发登录的性能测试场景:1s增加2个线程,运行2000次(线程数20,Ramp-Up seconds 10,循环次数100).分别看20.40.60并 ...
- [py][mx]django注册-邮件激活
人生,学习,就是一段旅途, 说是放弃,其实是自信心作祟. 因为不同时间段状态,譬如晚上和早上刚来状态不一样.做相同事情容器失去自信而放弃. 坚持可以打破这个魔咒 还有就是有些问题得分割, 不要让压死牛 ...