以前的知识总是忘,遇到代码又看不懂。要再复习一下,顺便记录一下。

 

关于立即执行函数: 

函数声明:function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明。

函数表达式 :var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。

匿名函数:function () {}; 使用function关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。

1 fnName();
 2 var fnName=function(){
 3     ...
 4 }//报错,变量fnName还未保存对函数的引用,函数调用必须在函数表达式之后
 5 
 6 var fnName=function(){
 7     alert('Hello World');
 8 }();//函数表达式后面加括号,当javascript引擎解析到此处时能立即调用函数
 9 
10 function fnName(){
11     alert('Hello World');
12 }();//报错,SyntaxError: expected expression, got ')'
13 
14 function(){
15     console.log('Hello World');    
16 }();//语法错误,虽然匿名函数属于函数表达式,但是未进行赋值操作,
17 //所以javascript引擎将开头的function关键字当做函数声明,报错:要求需要一个函数名

 

在函数体后面加括号要是能能立即调用,则这个函数必须是函数表达式,不能是函数声明。

 这样的函数,是函数表达式:

1   (function foo() {...})();
2   等同于:
3   var foo = function () {...};    
4   foo();
5   等价于:
6   (function foo() {...}());

 

 

没有括号括起来,报错,不能立即执行。用括号括起来,就好像要把函数体包成一个整体准备赋值给某个变量,只是没有这个变量。直接把这个整体立即执行。

对于JavaScript 来说,括弧()里面不能包含语句,所以在这一点上,解析器在解析function关键字的时候,会将相应的代码解析成function表达式,而不是function声明所以,只要将大括号将代码(包括函数部分和在后面加上一对大括号)全部括起来就可以了。 

 函数声明和函数表达式变量名同名,而且是两个不同函数,谁优先级高?

1   var hello=function (  ){
2  alert("hello");
3   }
4   hello(  );
5   function hello(  ){
6     alert("hello world");
7   }
8   hello(  );

 

答案是有变量名的函数表达式的优先级高。这里都输出: hello。

变成简单点的:

1 function  hello(  ){
2  alert("hello");  // hello world
3   }
4   hello(  );
5   function hello(  ){
6     alert("hello world");
7   }
8   hello(  ); //hello world      (完全一样的函数声明,后面的覆盖前面的)
1   var hello=function (  ){
2      alert("hello");
3   }
4   hello(  ); //hello
5   var hello=function hello(  ){
6     alert("hello world");
7   }
8   hello(  ); //hello world     (var hello是函数声明,按顺序给他们赋上函数,函数声明里的名字优先级没有变量名高)

 

 

 

作用域:

1 var scope="global";  
2 function t(){  
3     console.log(scope);   //ubdefined
4     var scope="local"  
5     console.log(scope);   //local
6 }  
7 t();

 

var scope="global";  是全局作用域,在函数里面,又定义了一个局部变量,变量提升。赋值未提升,所以是undefined,后面赋值了就是local

在C++等语言中,凡是有{}括起来的,都有块级作用域,但js没有,有函数作用域

当要调用一个对象时,它会从局部到全局,一个一个找,找到了就不继续找。

1 var name="global";  
2 if(true){  
3     var name="local";  
4     console.log(name)    //local
5 }  
6 console.log(name);    //local

 

if不是函数,没有块级作用域,它的上下文就是全局的。

相当于:

1   var name="global";  
2   var name="local";  
3   if(true){  
4         console.log(name)  
5   }  
6   console.log(name);

 

再看这个,从局部到全局,一个一个找,找到了就不继续找。

1 name="lwy";  
 2 function t(){  
 3     var name="tlwy";  
 4     function s(){  
 5         var name="slwy";  
 6         console.log(name);  
 7     }  
 8     function ss(){  
 9         console.log(name);  
10     }  
11     s();  //slwy
12     ss();  //tlwy
13 }  
14 t();

 

s()先在局部找,找到了var name='slwy'就输出了。

ss()在自己内部没有,就往上找,在t()函数内找,找到了var name='tlwy',也就输出了。

若没找到,就会继续在全局中找。这样就形成了一个作用域链,在最内部就是链头,没找到就沿着链找,链尾就是全局作用域了。

 

一个常见的问题,按钮,每次都是弹出最后一个:

1 var aLi = document.getElementsByTagName('li');
2 for(var i = 0; i < aLi.length; i++){
3   aLi[i].onclick = function(){
4     alert(i); // 每次都弹出最后一个的值
5   }
6 }

 

在页面加载完时,这个js函数就运行了,当我们点击时,它会去找i的值,最内部的匿名函数没有,就往上走,在外层找到了i,是4,就输出了4.

解决这方法:

1 for (var i = 0; i < aLi.length; i++) {
2     aLi[i].onclick = function (msg) {
3       show:function(){
4         alert(msg)
5 }
6 Return show;
7 })(i)
8 }
1 for (var i = 0; i < aLi.length; i++) {
2  (function(i){
3    aLi[i].onclick = function () {
4       alert(i);
5      };
6  })(i)
7 }

 

都是将他们保存起来

 

 文章用于学习记录,若有错误,望指正。