avaScript中除了自定义函数之外,还有匿名函数?什么是匿名函数?
1. 匿名函数:没有函数名称的函数。
如:定义一个匿名函数,打印5个星星。
<script>
function (){ //没有函数名称
for(var i=0;i<5;i++){
document.write("*");
}
}
</script>
2. 调用匿名函数有2种方法:
(1) 通过变量名调用匿名函数可以理解为将整个匿名函数渎职给一个变量
然后在body标签中,定义一个按钮:
(2) 事件名调用匿名函数
同样在在body标签中,先定义一个按钮:注意在input标签中我们不通过onclick来调用匿名函数
然后我们通过2个事件调用2个匿名函数:
注意:window.onload:页面加载时触发的事件,这里也就是页面加载进来调用第一匿名函数
document.getElementById("btn"):获取id为btn的元素,也就是将按钮获取过来;document.getElementById("btn").onclick:点击按钮时,触发第二个匿名函数
有两种方式:1、函数声明2、函数表达式 函数声明会提升 ,函数表达式不会。闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。由于作用域链的机制导致一个问题,循环里的 匿名函数取得的任何变量都是最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的变量。this对象 this对象是在运行时基于函数的执行环境绑定的,如果this在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window,因为闭包并不属于这个对象的属性或方法。
有两种方式:1、函数声明2、函数表达式
函数声明会提升,函数表达式不会。
函数声明,在执行函数之前会先读取函数声明。
sayhi()//‘hi’ function sayhi(){ console.log('hi'); } //不会出错
函数表达式
sayhi()//‘hi’ var sayhi=function(){ console.log('hi'); } //会出错
函数表达式和函数声明中没有函数名的函数,都是匿名函数
//不要这样做!,有的浏览器用第一个声明,有的用第二个 if(condition){ function sayHi(){ alert("Hi!"); } } else { function sayHi(){ alert("Yo!"); } } //可以这样做 var sayHi; if(condition){ sayHi = function(){ alert("Hi!"); }; } else { sayHi = function(){ alert("Yo!"); }; }
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
闭包可以让外侧函数的局部变量驻留内存,实现局部变量的累加,过度使用闭包导致性能下降,内存泄漏
function a(){ var age=1; return function(){ age++; return age; } } var x=a(); console.log(x())//2 console.log(x())//3
由于作用域链的机制导致一个问题,循环里的匿名函数取得的任何变量都是最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的变量。
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++) { console.log(b[i]()); //输出每个函数的值,都是最后一个值55555 }
因为b中存的是匿名函数对象,当bi执行匿名函数时,box()中的for循环早已执行完毕,i早已变成5.
解决方法1:让匿名函数自我执行
function box() { var arr = []; for (var i = 0; i < 5; i++) { arr[i] = (function(i) { return i; })(i); } return arr; } var b = box(); //得到函数数组 alert(b.length); //得到函数集合长度 for (var i = 0; i < b.length; i++) { console.log(b[i]); //输出0,12,3,4 }
解决方法2:匿名函数下在创建一个匿名函数,外侧匿名函数自执行
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(); //得到函数数组 alert(b.length); //得到函数集合长度 for (var i = 0; i < b.length; i++) { console.log(b[i]()); //输出 01234 }
this对象是在运行时基于函数的执行环境绑定的,如果this在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window,因为闭包并不属于这个对象的属性或方法。
var user='window'; var obj={ user:'obj', getUserName:function(){ return function(){ return this.user; } } } console.log(obj.getUserName()());//window
解决1:强制指向特定对象
console.log(obj.getUserName().call(obj));//obj console.log(obj.getUserName().apply(obj));//obj
解决2:复制this,得到上一个作用域的this对象
var user='window'; var obj={ user:'obj', getUserName:function(){ var that=this; return function(){ return that.user; } } } console.log(obj.getUserName()());//obj
for循环中的var i
在外部也能访问
function box(count) { for (var i=0; i<count; i++) {} var i; //就算重新声明,也不会覆盖前面的值,除非重新初始化 alert(i); } box(2);//2
解决1:
//模仿块级作用域(私有作用域)
(function () {
//这里是块级作用域
})();
//使用块级作用域(私有作用域)改写 function box(count) { (function () { for (var i = 0; i<count; i++) {} })(); alert(i); //报错,无法访问 } box(2);
解决2:ES6中使用let
function box(count) { for (let i=0; i<count; i++) {} alert(i); //i报错 } box(2);
参考资料:JavaScript高级程序设计(第3版)
数的编写与使用
在程序设计语言中函数是一段具有特殊功能的代码,同时也是一组可以重复使用的代码。通过函数这一对象的使用,进一步提高了程序开发的模块化与高度多的代码复用性。各种程序设计语言都对函数的定义及使用有着严格的语法规则。本文主要介绍如何在JavaScript中定义函数、使用函数,并对递归函数这一特殊类型函数进行说明。
JavaScript中所定义的函数主要由函数定义关键字、函数名称、函数参数、执行代码段与函数返回值5部分所组成。同时要求函数在使用过程中需要先定义函数,再调用函数。JavaScript函数定义基本语法描述如下:
JavaScript函数定义基本语法
JavaScript函数定义基本语法描述如上图,说明如下:
函数定义语法说明
函数定义完成之后,就可以通过调用该函数完成特定的功能。函数调用方式较为简单,只需要给出函数名称与所传递参数,如果参数为空,只需要给出名称后面的括号即可。关于参数部分需要注意形参与实参概念的区分。其中在函数定义中用于解释说明语言的参数为形参。在函数调用过程中替代形参参与实际运算的参数为实参。示例说明如下:
形参与实参示例说明
匿名函数(Anonymous function),顾名思义是指没有名字的函数,即在上面给出的基本语法中functionName部分可以省略的函数。在JavaScript中提供两类基本匿名函数定义方式,一种是将匿名函数封装为表达式,一种是将匿名函数赋值给变量形式。两类匿名函数基本语法描述如下:
匿名函数的定义形式
匿名函数定义形式描述如上图所示,上文中计算解决值函数我们可以使用两种方法改写为匿名函数,实现描述如下:
匿名函数使用实例
递归函数是一类特殊的函数类型,简单理解即为在一个函数的内部调用了该函数自身。在使用递归函数是需要注意产生递归的条件与递归终止的条件。如同循环控制语句一样,没有递归终止的条件,程序将会一直占用资源,无法结束释放资源。递归函数的说明可以从阶乘的计算这一案例展开说明。阶乘计算过程描述如下:
阶乘计算原理
阶乘计算过程描述如上图所示,我们可知阶乘问题的解决主要在于递推关系的挖掘与终止条件的确定。本例中递推关系为N!=N*(N-1)!,终止条件为1!=1;在明确这两点之后我们可以编写递归函数实现问题求解。递归函数描述如下图:
阶乘问题的递归求解编程实现
爬楼梯问题是使用递归算法进行问题求解的经典案例之一,爬楼梯问题主要只是假设有N阶楼梯,需要从最底层爬到最高层,在上楼过程中每步只允许上1层或者2层,计算爬到N层总共方法有多少种?
爬楼梯方法问题
爬楼梯方法问题采用递归思想还是比较简单的,我们可以从小人最后一步考虑。小人上到最高层N层时只能有两种方法:
①从N-2层跨越2层到达N层;
②从N-1层跨越1层到达N层;
则计算到达N层的方法f(n)就等于到达N-1层方法f(n-1)与达N-2层方法f(n-2)之和。这就找到了我们进行递推的关系式,终止条件即为f(1)=1和f(2)=2;
因此我们可以编程实现计算,实现代码如下:
爬楼梯递归求解代码
本头条号长期关注编程资讯分享;编程课程、素材、代码分享及编程培训。如果您对以上方面有兴趣或代码错误、建议与意见,可以联系作者,共同探讨。更多程序设计相关教程及实例分享,期待大家关注与阅读!JavaScript基础教程系列教程链接如下:
JavaScript基础教程(六)流程控制之循环语句
JavaScript基础教程(五)流程控制之条件语句
*请认真填写需求信息,我们会在24小时内与您取得联系。