javaScript之function定义

背景知识 

函数定义 
在javaScript中,function的定义有3种: 

1、匿名定义 
               function(){} 

2、非匿名定义 
               function fn(){} 
               fn = new Function(); 


触发函数执行 
对于匿名函数: 
                       (function(){})();       //执行一个匿名函数 
                       var f = function(){}(); //执行一个匿名函数,并将匿名函数的返回值,赋值给f 
                       !function(){}();        //执行一个匿名函数 
                  
              以上三种写法, 
              无非就是要把 匿名函数 作为一个表达式块 然后执行。 


对于非匿名函数: 
                       函数名();       //如: fn(); 


用法示例 
例子 1 
function add(x, y){ 
   return(x + y);  

例子 2 
var add = new Function("x", "y", "return(x+y)"); 

例子 3 
var fn = function(){ }  
将匿名函数的引用赋值给一个变量。(最常用的写法)如: 

var add = function(x, y){ 
   return(x + y);  

---------------------------------------------------------------- 
可以用如下代码行调用以上函数: 
add(2, 3); 

注意 : 在调用函数时,请确保包含了括号和必需的参数。调用函数时不用括号导致返回函数的文本而不是函数执行的结果。 
add(2, 3);// return  "5" 
add;      // renturn  " function add(x, y){return(x + y);} 




1、用法剖析 

Html代码  收藏代码
  1. <html>  
  2.         <head>  
  3.             <style type="text/css">  
  4.             p{  
  5.                 #CCCCCC;  
  6.                 height:20px;  
  7.                 100px;  
  8.                   
  9.               
  10.             }  
  11.             </style>  
  12.         </head>  
  13.     <body >  
  14.   
  15.         <p>test</p>  
  16.         <p>test</p>  
  17.         <p>test</p>  
  18.         <p>test</p>  
  19.         <p>test</p>  
  20.         <p>test</p>  
  21.   
  22.         <script type="text/javascript">  
  23.         /********************Method 1********************************/  
  24.         //常规的写法(正确的写法)  
  25.         /*  
  26.         var item=document.getElementsByTagName('p');  
  27.         for(var i=0;i<item.length;i++){  
  28.             item[i].onclick=(function(i){  
  29.                                 return function(){  
  30.                                            alert(i);  
  31.                                         }  
  32.                             })(i);  
  33.         }  
  34.   
  35.         */  
  36.         /********************Method 2********************************/  
  37.         //所有的 p 都 alert() 最后一个 i 的值(错误的写法)  
  38.         /*  
  39.         var item=document.getElementsByTagName('p');  
  40.         for(var i=0;i<item.length;i++){  
  41.             item[i].onclick=function(){  
  42.                 alert(i);  
  43.             };  
  44.         }  
  45.         */  
  46.           
  47.         /*  
  48.         说明:  
  49.         item[i].onclick=(function(){})(); 匿名函数与立即执行 ,然后把结果给item[i].onclick  
  50.         */  
  51.           
  52.         /********************Method 3********************************/  
  53.         //最能表达含义的写法(正确的写法)  
  54.         function createFunction(index){  
  55.             return function(){  
  56.                         alert(index);  
  57.                     }  
  58.         }  
  59.          
  60.         var elems = document.getElementsByTagName('p');  
  61.         for(var i=0,len=elems.length; i<len; i++){  
  62.             elems[i].onclick = createFunction(i);  
  63.         }  
  64.           
  65.           
  66.         /*说明:  
  67.         return function(){  
  68.                             alert(letter);  
  69.                         }  
  70.                           
  71.          =  
  72.            
  73.          return var fn = new Function(){  
  74.                             alert(letter);  
  75.                          }  
  76.                            
  77.            调用 function ,生成(定义)function.  
  78.            renturn 的 时候其实是 new 了一个function 出来。  
  79.      
  80.         */  
  81.   
  82.         </script>  
  83.     </body>  
  84. </html>  



2、运行效果图 

 





3、深入理解js的dom机制 


js的一切对象(包括函数)都是依赖于 html的dom而存在的。 

默认对象是window,所有的方法、属性,默认都是window对象的属性和方法 
--------------------------- 
alert() = window.alert() 
--------------------------- 
var x = window.x 
var x = 10; 
alert(window.x ); //10 

我们猜测所有js函数运行时的环境,也是基于某个对象的(该对象的属性就是其运行环境)。 

请看下面的例子: 

例子一 

Html代码  收藏代码
  1. <html>  
  2.     <head>  
  3.         <style type="text/css">  
  4.         p{  
  5.             200px;  
  6.             height:30px;  
  7.               
  8.         }  
  9.         </style>  
  10.     </head>  
  11.     <body>  
  12.         <p>test </p>  
  13.         <p>test </p>  
  14.         <p>test </p>  
  15.         <p>test </p>  
  16.         <p>test </p>  
  17.         <p>test </p>  
  18.         <script type="text/javascript">  
  19.         window.onload=function(){  
  20.             var adiv=document.getElementsByTagName('p');  
  21.             for(var i=0;i<adiv.length;i++){  
  22.                 adiv[i].onclick=function(){  
  23.                     alert(i);  
  24.                 }  
  25.             }  
  26.         }  
  27.         </script>  
  28.     </body>  
  29. </html>  


结果:(无论点那个都alert 6) 

 




例子二 

Html代码  收藏代码
  1. <html>  
  2.     <head>  
  3.         <style type="text/css">  
  4.         p{  
  5.             200px;  
  6.             height:30px;  
  7.               
  8.         }  
  9.         </style>  
  10.     </head>  
  11.     <body>  
  12.         <p>test </p>  
  13.         <p>test </p>  
  14.         <p>test </p>  
  15.         <p>test </p>  
  16.         <p>test </p>  
  17.         <p>test </p>  
  18.         <script type="text/javascript">  
  19.         window.onload=function(){  
  20.             var adiv=document.getElementsByTagName('p');  
  21.             for(var i=0;i<adiv.length;i++){  
  22.                 adiv[i].onclick=(function(i){  
  23.                     return function(){ alert(i);};  
  24.                 })(i);  
  25.             }  
  26.         }  
  27.         </script>  
  28.     </body>  
  29. </html>  


结果:(正常) 

 




原因: 

在例子二中, 
改变了onclick事件的function的作用域范围。 
(function(){ 
    return fuction(){}; 
})(); 
新new了一个function作用域,赋值给onclick事件。 



分析: 



例子一: 
当onclick触发时,它实际(引用)运行的环境是 window.onload , 
window.onload是一个function,而它又有自己的属性: 
window.onload.adiv 
window.onload.i 
window.onload.adiv[0].onclick 
window.onload.adiv[1].onclick 
window.onload.adiv[2].onclick 
window.onload.adiv[3].onclick 
... 

onclick 会在当前作用域中找adiv(找到了) ,也会去找 i ,但是此时 i 的值 是 adiv.leng-1 
所以会一直 alert 一个值 



而如下方式(例子二): 
window.onload=function(){ 
    var adiv=document.getElementsByTagName('p'); 
    for(i=0;i<adiv.length;i++){ 
        adiv[i].onclick=(function(i){ 
            return function(){alert(i)}; 
        })(i); 
        } 
    } 

是采用匿名函数立即执行,利用立即执行为匿名函数,window.onload为自身创建属性(一个匿名函数) 
此匿名又有2个属性(一个参数i,一个funcion) 
并把执行后的结果赋值给 adiv[i].onclick 
此时window.onload的结构大致是: 
window.onload.adiv 
window.onload.i 
window.onload.adiv[0].onclick 
window.onload.(function(0){}) 
window.onload.(function(0){}).i 
window.onload.(function(0){}).function 

window.onload.adiv[1].onclick 
window.onload.(function(1){}) 
window.onload.(function(1){}).i 
window.onload.(function(1){}).function 

... 

赋值后 
window.onload.adiv[0].onclick = 
window.onload.(function(0){}).function 

此时adiv[0].onclick的作用域是:window.onload.(function(0){}) 
                 不再是原来的:window.onload 

                 
在新的作用域中是有 i 的,而 i 的值,就是当初传进来的值。 
             



再看下面的例子: 

Html代码  收藏代码
  1. <html>  
  2.     <head>  
  3.         <style type="text/css"></style>  
  4.     </head>  
  5.     <body>  
  6.         <script type="text/javascript">  
  7.         /*  
  8.         //1.  
  9.         function Wen(){  
  10.             this.name = "taobao";  
  11.             this.waitMes=function(){  
  12.                 setTimeout(function(){this.fn(this.name);},1000);                   
  13.             };  
  14.             this.fn=function(name){  
  15.                 alert(name);  
  16.             }  
  17.         }  
  18.         var foo=new Wen();  
  19.         foo.waitMes();  
  20.           
  21.         //**运行结果:空。  
  22.         // *因为setTimeout 运行时的上下文环境是window  
  23.         // *而 window 没有 fn 和 name 属性  
  24.         //**故alert值为空  
  25.           
  26.         //2.  
  27.         var name = "taobao";         
  28.         function fn (name){  
  29.             alert(name);  
  30.         }         
  31.         function Wen(){  
  32.             this.waitMes=function(){  
  33.                 setTimeout(function(){this.fn(this.name);},1000);   
  34.             };  
  35.         }  
  36.         var foo=new Wen();  
  37.         foo.waitMes();  
  38.           
  39.         //**运行结果:非空。         
  40.         // *将 fn 和 name 放在 window 对象下  
  41.           
  42.           
  43.         //3.  
  44.         function Wen(){  
  45.             this.name = "taobao";  
  46.             this.waitMes=function(){  
  47.                 var that = this;  
  48.                 setTimeout(function(){that.fn(that.name);},1000);   
  49.             };  
  50.             this.fn=function(name){  
  51.                 alert(name);  
  52.             }  
  53.         }  
  54.         var foo=new Wen();  
  55.         foo.waitMes();  
  56.           
  57.         //**运行结果:非空。         
  58.         // *that作为参数传递到this中  
  59.         */  
  60.           
  61.        //4.   
  62.        function Wen(){  
  63.             this.name = "taobao";  
  64.             this.waitMes=function(){  
  65.                 var that = this;  
  66.                 setTimeout(that.fn,1000);   
  67.             };  
  68.             this.fn=function(){                 
  69.                 alert(this.name);  
  70.             };  
  71.              
  72.         }  
  73.         var foo=new Wen();  
  74.         foo.waitMes();  
  75.           
  76.         //**运行结果:非空。         
  77.         // *that作为参数传递到this中  
  78.           
  79.              
  80.         </script>  
  81.     </body>  
  82. </html>  


             

             

4、变量作用域之 变量覆盖 

原理: 
由于js function对象的 hoisting 特性(函数内的所有变量都相当于自动在函数头部声明,赋值部分位置不变), 
可能会导致访问变量时出现 undefined。 

例子: 

Javascript代码  收藏代码
  1.  <script type="text/javascript">  
  2.             //1.  
  3.             var foo = 'This is foo.';  
  4.             (function(){  
  5.                alert(foo);//This is foo.  
  6.             })();  
  7.               
  8.             //2.  
  9.             var foo = 'This is foo.';  
  10.             (function(){  
  11.                alert(foo);//undefined  
  12.                var foo = 2;  
  13.             })();  
  14.               
  15.             /** 
  16.             function对象的 hoisting 特性:函数内的所有变量都相当于自动在函数头部声明 
  17.             故 2 等价于这种写法: 
  18.              
  19.             var foo = 'This is foo.'; 
  20.             (function(){ 
  21.                var foo; 
  22.                alert(foo); 
  23.                foo = 2; 
  24.             })(); 
  25.             
  26.             在2中,又定义了一个局部变量foo,(覆盖了上级范围的foo),但是没有给赋初值, 
  27.             故访问foo时,出现 undefined 提示。 
  28.             */  
  29. </script>  



所以,在函数定义时,其所有用到的变量,要写在函数体前。 








补录: 
--- 
匿名函数自动执行,只是一种简便的写法而已,并无新奇或创意。 
(function(){})(); 
等价于 
var fn = function(){}; 
fn();//执行 
在任何使用过程中,完全可以用后一种方式替代。 

原文地址:https://www.cnblogs.com/xiaochao12345/p/3816452.html