背景知识

函数定义 
在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、运行效果图

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)

例子二

  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>

结果:(正常)

原因:

在例子二中, 
改变了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();//执行 
在任何使用过程中,完全可以用后一种方式替代。

最新文章

  1. Linux终端使用代理服务器
  2. 重走java---Step 1
  3. MyBatis学习总结(三)&mdash;&mdash;优化MyBatis配置文件中的配置
  4. 如果把表单数据的校验交给了javascript那么后台还有没有必要对数据做校验呢
  5. 【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测(lct/并查集)
  6. redhat enterprixe 5.0 NFS服务配置与管理
  7. [oracle]一个最简单的oracle存储过程&quot;proc_helloworld&quot;
  8. 如何编写Linux设备驱动程序
  9. LR参数化设置(转)
  10. hbulider 快捷键以及常用
  11. MVC接收以post形式传输的各种参数
  12. Square spiral
  13. oracle rac ha
  14. 纯注解快速使用spring IOC容器
  15. 在DLL中导出另一静态库中的函数
  16. gradle build docker image
  17. selenium python 设置窗口打开大小
  18. How to enable usb on vbox
  19. Gym 101775A - Chat Group - [简单数学题][2017 EC-Final Problem A]
  20. Python:每日一题006

热门文章

  1. python练习笔记——分解质因数
  2. 转Jmeter报告优化之New XSL stylesheet
  3. Unix环境高级编程(十九)终端I/O
  4. Go 语言官方包函数中文翻译
  5. linux下安装nginx和配置
  6. gradle平级项目引用
  7. python标准库介绍——3 stat 模块详解
  8. Tree通用的系列方法列表-treepanel
  9. ubuntu中pip安装redis-py及pip的使用
  10. mod_fastcgi和mod_fcgid的区别