匿名函数
在JavaScript这门脚本语言中,默认的定义函数格式如下:
function fn(a,b){ console.log(a+b); }
某些情况下定义函数时会省略掉函数名称如下:
function (a,b){ console.log(a+b); }
这样的函数就叫做匿名函数。
而众所周知,函数是通过函数名来调用的,当没有名字时该如何调用,用在什么地方呢?
调用方式
一:放进变量中
let myfn = function(a,b) { console.log(a+b); }; myfn(1,2);
这样一来,这个变量就相当于函数名,因此这个函数就等于是个普通函数了
二:直接执行
常用方式
- (匿名函数)()
- (匿名函数())
(function(a,b){ console.log(a+b); })(1,2) (function(a,b){ console.log(a+b); }(1,2))
三:利用事件调用
let btn = document.getElementById("btn"); btn.onclick = function() { console.log("clicked!"); }
四:作为对象的方法调用
let myobj = { name:"yumefx", hello:function(){ console.log("hello,"+this.name); } }; myobj.hello();
这种方法与第一种方法赋予变量类似。
五:作为另一个函数的参数
function myfn(fn){ fn(); } myfn(function(){ console.log("yes"); });
变量作用域
在ES6之前,当使用var声明变量时,只有全局作用域和函数作用域。
以函数声明为界,函数内部变量和外部变量是两个不同的作用域,内部声明的变量不可以在外部被访问,而内部可以调用和覆盖外部声明的所有变量,即使外层函数已经执行完毕(作用域嵌套)。
var tmp = new Date(); function f() { console.log(tmp); if (false){ var tmp = "hello"; } } f(); //undefined
这段代码中,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是由于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
所谓变量提升,就是将函数和变量的声明提升到当前作用域的最顶端,因此要想变量不是全局变量,那么就得用函数包起来。变量提升的结果就是声明的变量在声明前调用值为undefined而不会报错。
除此以外还有内存泄漏问题,例如用来计数的循环变量泄露为全局变量。
var s = "hello"; for (var i = 0; i < s.length; i++){ console.log(s[i]); } console.log(i);
在ES6之后,有了一个新的变量声明符号let,可以声明块级作用域,只有在当前代码块内有效,并且无法在声明前调用(let不存在变量提升)。
a //undefined { var a = 1; let b = 2; } a //1 b //ReferenceError: b is not defined.
另外,let不能在同一作用域内,重复声明同一个变量,例如不能在函数内部重新声明传入的参数。因此,匿名函数的闭包功能,其实就是在let出现前,将某些变量变成类似块级作用域的方式。
优点是可以防止内部变量污染外部变量,但要小心this指向、变量作用域、内存泄漏等问题。
this指向
var object = { name: "object", getName: function() { return function() { console.info(this.name) } } } object.getName()() //undefined
因为里面的闭包函数是在windows作用域下执行的,因此,this指向windows。
变量作用域
function outer() { var result = []; for (var i = 0; i < 10; i++){ result[i] = function() { console.info(i) } } return result; }
看起来似乎是输出等差数列0,1,2,3,4,…,9,实际上因为每个闭包函数访问变量i是outer执行环境下的变量i,随着循环的结束,i已经变成10了,所以最后打印出的是10,10,10,…,10
解决这个问题如下:
function outer() { var result = []; for (var i = 0; i < 10; i++){ result[i] = function(num) { return function() { console.info(num) } } } return result; }
这样访问的num,是上层函数执行环境的num,数组有10个函数对象,每个对象的执行环境下的number都不一样。
内存溢出
function showId() { var el = document.getElementById("app"); el.onclick = function(){ alert(el.id); } }
上面这样写会导致闭包引用外层的el,当执行完alert后,el无法释放内存。修改如下:
function showId() { var el = document.getElementById("app"); el.onclick = function(){ alert(el.id); } el = null; //主动释放el }
使用闭包解决递归调用问题
function factorial(num) { if(num <= 1) { return 1; }else{ return num * factorial(num-1); } } var anotherFactorial = factorial; factorial = null; anotherFactorial(4);
这样写是有问题的,因为最后是return num* argument.callee(num-1),argument.callee指向当前执行函数,但是在严格模式下不能使用该属性也会报错。
借助闭包实现修改如下:
function factorial = (function f(num) { if(num <= 1) { return 1; }else{ return num * factorial(num-1); } })
这样实际起作用的是闭包函数f,而不是外面的函数factorial。
每个人都经历着受骗和伤痛,
最终掌握了在这条街道生活下去的本领。
《我的晃荡的青春》
——东野圭吾
评论
856973 684954Black Ops Zombies is now available […]Take a appear here[…] 804863
467133 35258Thanks for all your efforts which you have put in this. extremely fascinating info. 434150
850852 780828Extremely informative and wonderful complex body part of articles , now thats user pleasant (:. 634214
61647 130245Utterly composed topic material , thanks for selective information . 547253
517339 881683I like the valuable information you offer within your articles. Ill bookmark your weblog and check once again here often. Im quite certain I will learn a lot of new stuff right here! Good luck for the next! 278935
849778 989607informatii interesante si utile postate pe blogul dumneavoastra. dar ca si o paranteza , ce parere aveti de inchirierea apartamente vacanta ?. 468561
14645 953947I just could not go away your website before suggesting that I very enjoyed the usual information a person supply to your guests? Is going to be back ceaselessly so that you can inspect new posts. 618339
As a Newbie, I am constantly exploring online for articles that can help me. Thank you
http://www.tlovertonet.com/
19492 638273One can undertake all sorts of advised excursions with assorted limousine functions. Various offer great courses and many can take clients for just about any ride your bike over the investment banking region, or even for a vacation to new york. ??????? 117921
418108 201805Lovely sharp post. Never considered that it was that simple. Praises to you! 234279
34721 711277Wohh just what I was searching for, thanks for putting up. 127007