javaScript之function定义

时间:2024-08-24 13:03:32

背景知识

函数定义 
在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、用法剖析

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

2、运行效果图

javaScript之function定义

3、深入理解js的dom机制

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

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

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

请看下面的例子:

例子一

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

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

javaScript之function定义

例子二

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

结果:(正常)

javaScript之function定义

原因:

在例子二中, 
改变了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 的值,就是当初传进来的值。

再看下面的例子:

  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. // *因为setTimeout 运行时的上下文环境是window
  22. // *而 window 没有 fn 和 name 属性
  23. //**故alert值为空
  24. //2.
  25. var name = "taobao";
  26. function fn (name){
  27. alert(name);
  28. }
  29. function Wen(){
  30. this.waitMes=function(){
  31. setTimeout(function(){this.fn(this.name);},1000);
  32. };
  33. }
  34. var foo=new Wen();
  35. foo.waitMes();
  36. //**运行结果:非空。
  37. // *将 fn 和 name 放在 window 对象下
  38. //3.
  39. function Wen(){
  40. this.name = "taobao";
  41. this.waitMes=function(){
  42. var that = this;
  43. setTimeout(function(){that.fn(that.name);},1000);
  44. };
  45. this.fn=function(name){
  46. alert(name);
  47. }
  48. }
  49. var foo=new Wen();
  50. foo.waitMes();
  51. //**运行结果:非空。
  52. // *that作为参数传递到this中
  53. */
  54. //4.
  55. function Wen(){
  56. this.name = "taobao";
  57. this.waitMes=function(){
  58. var that = this;
  59. setTimeout(that.fn,1000);
  60. };
  61. this.fn=function(){
  62. alert(this.name);
  63. };
  64. }
  65. var foo=new Wen();
  66. foo.waitMes();
  67. //**运行结果:非空。
  68. // *that作为参数传递到this中
  69. </script>
  70. </body>
  71. </html>

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

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

例子:

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

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

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