浅谈JavaScript的函数表达式(闭包)

  前文已经简单的介绍了函数的闭包。函数的闭包就是有权访问另一个函数作用域的函数,也就是函数内部又定义了一个函数。

1 var Super=function(num){
2                         var count=num;
3                         return function(){
4                             console.log(count);
5                         }
6                     }
7                     var result=Super(3);//此时result是一个函数
8                     result();//输出3

  上面的代码定义了一个函数Super,同时在Super函数内部又定义了一个匿名函数作为返回值。第七行调用Super函数,此时result是一个函数。第8行执行了result函数,输出为3。这就是闭包的体现,因为上面的Super函数已经执行结束,但是它的内部变量count的值依然没有被释放,count的还在被匿名函数引用,所以没有办法释放。如果要释放count,我们需要 result=null ,将null赋值给result。

  在前文已经介绍了函数的作用域链,当函数第一次被调用时会创建一个作用域链,并作用域链赋值给一个特殊的内部属性。在作用域链中,函数的外部函数的活动对象位于第二位,外部函数的外部函数的活动对象位于第三位,以此类推,全局变量的作用域链位于最底部。

 1 var count=2;
 2 console.log(count);//2
 3 count=3;
 4 console.log(count);//3
 5 var Super=function(num){
 6 var count=num;//作用域链第二位
 7 console.log(count);//1
 8 return function(){
 9 var count=5;//作用域链第一位
10 console.log(count);
11 }
12 }
13 var result= new Super(1);
14 result();//输出5

  上面的代码中,能够清晰地了解到变量的作用域。闭包函数的内部变量位于最顶端,全局变量位于最底部。

  在闭包中使用this对象也可能会导致一些问题,this对象是在函数运行时,基于函数的执行环境绑定的。在全局函数中,this指向window对象。而函数作为某个对象的方式调用时,this等于那个对象。不过匿名函数的执行环境具有全局性,因此this指向window

 1 var obj={
 2                         name:"heh",
 3                         getName:function(){
 4                             var that=this;
 5                             return function(){
 6                                 return that.name;
 7                             }
 8                         }
 9                     };
10                     var one=obj.getName();
11                     var name=one();//heh

  上面的代码中,通过字面量的方式创建了对象obj,定义了对象的属性name和方法getName。但是在getName内部,我们定义了闭包函数。如果想在闭包函数中访问name,通过this是访问不到的。所以需要在闭包函数的外部定义一个变量that,指向this。在getName中定义的变量,在闭包函数中仍然可以继续使用。

  JavaScript中没有块级作用域的概念,这意味着块级中定义的变量,实际在函数内部都是可以使用的。

1 for(var i=0;i<10;i++){
2                         console.log(i);
3                     }
4                     console.log(i);//输出10

  上面的代码中,我们在for循环中定义了变量i,但是我们在for循环外部依然可以使用i。for循环结束后,i变量并没有被销毁。

  JavaScript可以使用匿名函数来模仿块级作用域,从而避免该类问题的发生。

  

1 (function(){
2                         for(var i=0;i<10;i++){
3                             console.log(i);
4                         }
5                     })();
6                     console.log(i);

  上面的代码中,我们将块级作用域放在了一个匿名函数中,同时将匿名函数放在一对括号中,这表示一个函数表达式。在函数表达式外部的括号,表示立即调用该函数。在第六行调用该函数的时候,会发生报错,因为i并没有定义。

  

1 var testFunc=function(){
2                         for(var i=0;i<10;i++){
3                             console.log(i);
4                         }
5                     };
6                     testFunc();
7                     console.log(i);

  这个代码,和我们上面的代码是一样的,都是通过函数表达式来定义函数。

  

1 function(){
2                         for(var i=0;i<10;i++){
3                             console.log(i);
4                         }
5                     }();

  上面的代码是错误的。我们知道函数的定义方法,可以通过function和函数表达式。通过function声明函数的时候,function后面不能跟圆括号。函数表达式的后面可以跟圆括号。

  

1 var testFunc=function(){
2                         for(var i=0;i<10;i++){
3                             console.log(i);
4                         }
5                     }();

  一般来说在开发过程中,应该尽量少向全局对象中添加函数和变量。太多的全局函数和变量容易导致命名的冲突以及内存的泄露。我们可以在块级函数中完成所有的操作。

  

1 (function(){
2                         var now = new Date();
3                         console.log(now.getFullYear()+"-"+(now.getMonth()+1)+"-"+now.getDate()+" "+now.getHours()+":"+now.getMinutes()+":"+now.getSeconds());
4                     })();

  通过上面的代码,我们能够当前的日期和时间。

  

原文地址:https://www.cnblogs.com/ggz19/p/8435546.html

时间: 2024-11-05 06:11:46

浅谈JavaScript的函数表达式(闭包)的相关文章

浅谈JavaScript的函数表达式(递归)

递归函数,在前面的博客中已经简单的介绍了.递归函数是一个通过函数名称在函数内部调用自身的函数.如下: 1 function fac(num){ 2 if(num<1){ 3 return 1; 4 } 5 else{ 6 return num*fac(num-1); 7 } 8 } 上面的代码,在第一行声明了一个fac函数,同时在6行调用了fac函数本身.这是一个求阶乘的递归函数. 1 var anthorfacc=fac; 2 fac=null; 3 anthorfacc(4);//抛出异常

浅谈JavaScript匿名函数与闭包

一. 匿名函数 //普通函数定义: //单独的匿名函数是无法运行的.就算运行了,也无法调用,因为没有名称. 如: function(){ alert('123'); }                        //语法错误,无法执行 1.简单的使用: var box =  function(){ return 'Lee'; } alert (box());        //需要调用box()方法. 2.通过自我执行来执行匿名函数 (function(){                /

浅谈javascript的函数节流

什么是函数节流? 介绍前,先说下背景.在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(其核心就是绑定mousemove),这种事件有一个特点,就是用户不必特地捣乱,他在一个正常的操作中,都有可能在一个短的时间内触发非常多次事件绑定程序.而大家知道,DOM操作时很消耗性能的,这个时候,如果你为这些事件绑定一些操作DOM节点的操作的话,那就会引发大量的计算,在用户看来,页面可能就一时间没有响应,这个页面一下子变卡了变慢了.甚至在IE下,如果你绑定的resize事件进行

【JavaScript系列】浅谈JavaScript之函数(一)

在编程语言中,无论是面向过程的C,兼备面过程和对象的c++,还是面向对象的编程语言,如java,.net,php等,函数均扮演着重要的角色.当然,在面向对象编程语言JavaScript中(严格来说,JS属于弱面向对象编程语言),函数(function)更扮演着极其重要的角色和占有极其重要的地位.在本 ... 653rai悼抑戳眯陨桨<http://baobao.baidu.com/question/ba4ad4dffdea7da838c2d08783ca1801.html?=D>435rqv示

浅谈JavaScript eval() 函数

用js的人都应该知道eval()函数吧,虽然该函数用的极少,但它却功能强大,那么问题来了,为什么不常用呢?原因很简单,因为eval()函数是动态的执行其中的字符串,里面有可能是脚本,那么这样的话就有可能引发系统的安全问题,所以能不用就不用,但至少也要知道它的用法. eval()函数的作用简单来说就是用来把括号中的字符串当作代码来执行,举个简单的例子,eval("2+3") ,返回的就是5.需要注意的是该方法就受的只能是原始的字符串参数,如果不是的话它将什么都不会做原样返回,所以你给它传

《浅谈JavaScript系列》系列技术文章整理收藏

<浅谈JavaScript系列>系列技术文章整理收藏 1浅谈JavaScript中面向对象技术的模拟 2浅谈javascript函数劫持[转自xfocus]第1/3页 3浅谈javascript 面向对象编程 4老鱼 浅谈javascript面向对象编程 5浅谈javascript的数据类型检测 6浅谈Javascript嵌套函数及闭包 7根据一段代码浅谈Javascript闭包 8浅谈JavaScript编程语言的编码规范 9浅谈Javascript面向对象编程 10浅谈JavaScript

浅谈javascript函数劫持

http://www.xfocus.net/articles/200712/963.html 浅谈javascript函数劫持 文章提交:hkluoluo (luoluonet_at_hotmail.com) by luoluo on 2007-11-30 luoluonet_at_yahoo.cn http://www.ph4nt0m.org 一.概述 javascript函数劫持,也就是老外提到的javascript hijacking技术.最早还是和剑心同学讨论问题时偶然看到的一段代码,大

浅谈 JavaScript 编程语言的编码规范

对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编码规范也往往被轻视,开发过程中修修补补,最终也就演变成为后续维护人员的恶梦.软件存在的长期价值直接与编码的质量成比例.编码规范能帮助我们降低编程中不必要的麻烦.而 JavaScript 代码是直接发送给客户浏览器的,直接与客户见面,编码的质量更应该受到关注. 本文浅谈 JavaScript 编程中关

浅谈javascript单体【读javascript设计模式第五章节单体有感】

单体,整个运行环境就独有一份,最简单的一种单体就是一个把所有属性和方法都集中在一起的对象,区别于一般的字面量对象,一般字面量对象是对一个物体的描述,集合该物体所具有的一些属性和方法,而单体则包含更多的些逻辑在里面,单体的好处有,划分命名空间,如果用来作为网页包装器,可以使得页面所有变量都封装在一个对象里,大幅度减小网页里的全局变量, 代码如: common.js (function(wz){ $.extend({ init:function(){ var self = this; this.bi