自执行匿名函数:
?常见格式:(function() { /* code */ })();
?解释:包围函数(function(){})的第一对括号向脚本返回未命名的函数,随后一对空括号立即执行返回的未命名函数,括号内为匿名函数的参数。
?作用:可以用它创建命名空间,只要把自己所有的代码都写在这个特殊的函数包装内,那么外部就不能访问,除非你允许(变量前加上window,这样该函数或变量就成为全局)。各JavaScript库的代码也基本是这种组织形式。
总结一下,执行函数的作用主要为 匿名 和 自动执行,代码在被解释时就已经在运行了。
其他写法:
(function () { /* code */ } ());
!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
+function () { /* code */ } ();
变量声明提升
先看以下代码:
1)var in_window = “a” in window; console.log(in_window);
2)var in_window = “a” in window; console.log(in_window); if(!(“a” in window)) { var a = 1; }
3)var a; var in_window = “a” in window; console.log(in_window); if(!(“a” in window)) { a = 1; }
控制台输出的结果分别是:false true true。如何解释?
这是由于在js的变量作用域中有个规则:所有变量声明都在范围作用域的顶部!也就是说,在2)代码中,if语句块内的申明的变量a,会自动提到上面去申明。其等价于3)。
理解JavaScript变量声明行为的一个好办法是把变量声明看作由两部分组成,即声明和赋值。JavaScript隐式地提升(hoists)声明部分到封闭函数的顶部,而将赋值留在原地。换句话说,变量的作用域是整个函数,但仅在var语句出现的位置进行赋值。图2.2提供了变量声明提升的可视化图。
由上述的分析可知,可以理解下面代码的输出结果是undefined。
if(!("a" in window)) { var a = 1; } console.log(a); //undefined
该代码其实相当于:
var a; if(!("a" in window")) { a = 1; } console.log(a);
什么是块级作用域呢?
任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
函数作用域就好理解了,定义在函数中的参数和变量在函数外部是不可见的。
因为js没有块级作用域,所以需要使用闭包来防止全局命名空间的污染。
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
f2就是一个闭包,f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
<script>
function f1(){
var a=1;
function f2(){
var b=2;
var c=a+b;
alert(c+":f2");
}
return f2;
}
alert(f1()());//f1()()加了括号后,相当于var f1=function(){...};f1();
/*
f1()返回的是一个函数的指针
(function f1(){...})()//function f1()加了括号后,相当于var f1=function(){...}; f1();
但是不能这样写:function f1(){...}(),因为function f1(){...}只是一个函数声明,并不会被执行,
加了括号以后,函数声明被转化为表达式,会被执行,返回一个指针f2后,在与最后一个()结合成为表达式被执行。
*/
</script>
变量声明提升:(是在函数作用域内提升,)
<script>
function(){
var a=1;
alert(a);//1
alert(b);//undefined
alert(c);//unexpected identifier 错误,不会执行下一行
var b=2;//此处将变量b的声明提升,因为上一行报错,所以不执行b=2赋值。
}
/*
相当于
function(){
var a;//手动变量声明提升
var b;//手动变量声明提升
a=1;
alert(a);
alert(b);
alert(c);
b=2;
}
*/
</script>