受不了了,寒假我是有把《你不知道的javascript》上卷看完,就看着画了一下重点,这不,开学了,看见人家博客上讲setTimeOut()啥的,突然发现,自己看了是白看啊!!今晚速速捡起来,整理成博客!
函数作用域
函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也可以使用)
对函数作用域的利用:
在任意代码片段外部添加包装函数,可以将内部的变量和函数定义“隐藏”起来,外部作用域无法访问包装函数内部的任何内容。
一般写法:
var a =2;
function foo(){
var a = 3;
console.log(a); //3
}
foo();
console.log(a); //2
缺点:
1. 必须声明一个具名函数foo() , 意味着foo这个名称本身”污染”了所在作用域
2. 必须显式通过函数名( foo())调用这个函数才能运行其中的代码
3.
解决方案:
var a =2;
(function foo(){
var a =3;
console.log(a); //3
})();
console.log(a); //2
区分函数声明和表达式最简单的方法是看function关键字出现在声明中的位置(
不仅仅是一行代码,而是整个声明中的位置)。
函数声明 function test() {};
函数表达式 var test = function() {};如果function是声明中的第一个词,那就是一个函数声明,否则就是一个函数表达式
区分声明和函数表达式之间最重要的区别是它们的名称标识符将会绑定在何处
第一个代码片段中foo被绑定在所在作用域中,可以直接通过foo()来调用它
第二个代码片段(function foo(){…})
中foo被绑定在函数表达式自身的函数中,只能在…所代表的位置中被访问,外部作用域找不到foo
匿名函数表达式
setTimeout( function() {
console.log("I am here") ;
} , 1000 ) ;
缺点:
1. 在栈追踪中不会显示有意义的函数名,使得调试很困难
2. 当函数需要引用自身时只能使用已经过期的argument.callee引用
3. 代码可读性差
推荐 行内函数表达式,给函数表达式指定一个函数名
setTimeout( function() timeoutHander {
console.log("I am here") ;
} , 1000 ) ;
立即执行函数表达式
IIFE(Immediately Invoked Function Expression)
(function foo(){...})() 第一个()将函数变成了表达式,第二个()执行了这个函数
或者(function foo(){...}())
把 I IFE当作函数调用并传递参数进去
var a = 2 ;
(function foo1( global ){
var a = 3;
console.log( a );
console.log( global.a );
})(window);
console.log( a );
我们将window对象的引用传递进去,把参数命名为global。
导致代码的运行顺序
将需要运行的函数放在第二位,在I I FE执行之后当作参数传递进去
!!我运行 出错了!global.a 是undified! 苦恼
var a = 2 ;
(function fooo( def ){
def( window ) ;
})(function def( global){
var a = 3 ;
console.log( a ); //3
console.log( global.a ); // 2
});
函数表达式def定义在片段的第二部分,然后当作参数(这个参数也叫做def)被传递进IIFE函数定义的第一部分。最后,参数def(也就是传递进去的函数)被调用,并将window传入当作global参数的值