函数声明时必须有函数名bash
function fn(){};
复制代码
函数表达式中的函数能够为匿名函数,也能够有函数名,可是该函数不能直接使用,只能经过表达式左边的变量 fn 来调用闭包
var fn = function(){};
复制代码
function a(){
console.log("函数声明");
}
var b = function(){
console.log("函数表达式");
}
a(); //函数申明
b(); //函数表达式
复制代码
a(); //函数声明
b(); //报错
function a(){
console.log("函数声明");
}
var b = function(){
console.log("函数表达式");
}
复制代码
为何会有这样的结果?
缘由: function a(){} 为函数声明,程序运行前就已经存在;var b = function(){} 为函数表达式,属于按顺序执行,因此 b() 会报错函数
在ES5中,是没有块级做用域的概念的;咱们主要经过匿名函数的方式来块级做用域。
用做块级做用域(私有做用域)的匿名函数的语法:ui
(function() { //此处是块级(私有)做用域 })();
!function () { //此处是块级(私有)做用域 } ();
~function () { //此处是块级(私有)做用域 } ();
-function () { //此处是块级(私有)做用域 } ();
+function () { //此处是块级(私有)做用域 } ();
//这些都是当即执行的函数表达式的写法
//定义并当即调用了一个匿名函数。将函数声明包含在一对圆括号中,表示它其实是一个函数表达式。
复制代码
var a = function() { console.log("IIFE 写法的产生"); };
a(); //IIFE 写法的产生
//咱们将一个匿名函数赋值给了一个全局变量a,而后调用了这个函数
复制代码
(function(){
console.log("这是一个当即执行的函数");
})();
//第一个圆括号:将匿名函数转换为函数表达式
//第二个圆括号:当即执行匿名函数(固然,你也能够设置一个函数名)
复制代码
总结: 1. 建立块级(私有)做用域,避免了向全局做用域中添加变量和函数,所以也避免了多人开发中全局变量和函数的命名冲突
2.IIFE中定义的任何变量和函数,都会在执行结束时被销毁。这种作法能够减小闭包占用的内存问题,由于没有指向匿名函数的引用。只要函数执行完毕,就能够当即销毁其做用域链spa
预期: 使用 setTimeout 循环输出 0 1 2 3 4 5code
for(var i = 0; i <= 5; i++){
setTimeout(function timer(){
console.log(i);
}, i*1000);
}
//结果:1秒内输出6个6
复制代码
缘由: 超时的回调函数都将在循环完成以后当即运行。
解决方法:内存
方法一:
for(var i = 0; i <= 5; i++){
(function(){
var j = i;
setTimeout(function timer(){
console.log(j);
}, j*1000)
})();
}
//结果: 0 1 2 3 4 5
复制代码
方法二:
for(var i = 0; i <= 5; i++){
(function(j){
setTimeout(function timer(){
console.log(j);
}, j*1000)
})(i);
}
//结果: 0 1 2 3 4 5
复制代码
IIFE 为每次迭代建立了新的做用域,这给了超时回调函数一个机会在每次迭代时闭包一个新的做用域。作用域