JS中的函数与闭包

JavaScript中的函数由于其独特的功能和特性大大增强了JS的编程实力。在JS中函数也是对象,所以可以为它添加属性和方法,但typeof操作符对函数返回字符串’fnuction’,原生的toString()方法返回代表这个函数的源代码。

一、函数的实质
      函数本身也是JS中创建的一种变量(准确分类为对象),它由一系列可执行代码+name属性+形参列表组成。函数可以通过name属性或者变量名来调用。函数具有函数作用域,相对于全局作用域对程序执行环境的变换进行控制。

二、函数的定义
      函数可以有三种定义方式,最常用的是var变量声明也就是函数定义表达式和function关键字声明。这两种方式的不同之处在于:1、函数声明方式会使 得函数声明提升,即可以在函数声明之前合法使用函数,函数定义表达式方式只会使函数名提前,但可执行代码等并没有得到声明;2、每个函数都有一个name 属性,代表函数的名字,使用函数声明定义的函数name属性不为空,使用函数定义表达式定义的函数成为匿名函数,name属性是空字符串。JS中不建议使 用构造函数模式定义函数,消耗内存,效率也比较低。

三、函数的局部作用域
      JavaScript中没有块级作用域,for循环结构等内部并不存在局部变量这种说法。但函数有局部作用域,函数内部的形参列表、变量、内嵌函数都是属 于该局部作用域的局部变量或函数,只能在该函数内部使用,一般情况下当函数执行结束(即遇到return语句或者执行到代码末尾时)后会被JS内存管理机 制当做“垃圾”回收掉。

四、函数的调用
      1、作为对象的方法调用,此时执行上下文是该对象;
      2、作为普通函数调用,无论是在全局中调用还是在某个函数内部调用,执行上下文都是全局作用域;
      3、作为构造函数调用,此时执行上下文是新创建的那个对象实例;
      4、作为对象冒充中的函数调用即使用call或者apply方法时,执行上下文是那个间接调用该函数的对象。

五、函数词法分析过程
      在函数运行之前会有一个预编译也就是词法分析过程,这个过程如下:
      1、分析形参列表,将形参变量作为属性保存在AO活动对象中,属性值为undifined;
      2、分析函数内部声明的变量,如果AO对象中还没有这个属性,则保存这个属性,值为undifined,如果已有这个属性则什么也不做;
      3、分析内嵌函数,如果AO中没有同名属性,则添加这个属性(作为方法保存),如果已有同名属性,则覆盖之前的属性。
      函数词法分析时只是决定了该函数的AO对象中有哪些属性,是变量还是函数,变量的值都是undifined,当函数运行时才会给AO对象中的属性赋值!

六、函数最棒的特性——闭包

1、闭包的形成原理及实质
      闭包是指这样一种函数,它内嵌于某个函数中,那么它的作用域链就会关联所有外层函数和全局作用域的变量对象,也就是说它可以访问所有外层函数和全局作用域 中的变量对象。全局作用域的变量对象要等到程序执行结束之后才会被回收,如前所述,外层函数的变量对象在一般情况会在函数执行结束后被回收掉。可是如果出 现这样的情况,这个或这几个闭包被外层函数作为返回值返回或者作为返回值的方法返回(外层函数返回一个对象,闭包作为这个对象的方法也被返回),这若干个 闭包共享这些被滞留下来的变量对象。总而言之就是闭包被保存下来了,那么闭包本身的变量对象不会被销毁,更重要的一点就是闭包最大的作用——它会使得它所 关联到的变量对象(即所有外层函数的变量对象)都滞留内存,不会被回收!从使用变量的角度看,那些变量对象从此只能通过这个闭包访问了。

2、闭包的作用
        (1)实现缓存机制,节约计算机资源,加快执行速度提高效率;
        (2)实现私有变量的封装;
        (3)实现面向对象中的对象。

3、闭包带来的问题
        (1)、可能会因为造成循环引用导致内存泄露;
        (2)、由于闭包滞留内存,会比较消耗资源;
        (3)、同一次的执行结果生成的闭包共享该次滞留下来的变量对象,可能会造成开发人员意料之外的结果,比如在循环中绑定事件处理函数。

原文地址:www.bfy0412.com

时间: 2024-10-07 05:50:15

JS中的函数与闭包的相关文章

JS中的作用域和闭包

作用域:在编程语言中,作用域控制着变量与参数的可见性及生命周期.JS确实有函数作用域,那意味着定义在函数中的参数和变量在函数外部是不可见的,而且在一个函数中的任何位置定义的变量在该函数中的任何地方都是可见的. var a = 1; var fs = function (){ var b = 2; var c = 4 var fun = function (){ var c = 3; alert(a) //输出1 alert(b) //输出2 alert(c) //输出3 } fun(); } f

js中一些函数(一)【丫头, 今天去哪儿了呢,好些没有】

Math.Rondom()   ==>  0 到 1 之间的小数 Math.floor(x)  ==>  小于或者等于 x 的整数(即转换成整数后是不能比 x 大的整数) setInterval(hanshu,1000)  ==>  意思为调用下面的 hanshu(), 间隔时间为 1000 ms(毫秒) js中一些函数(一)[丫头, 今天去哪儿了呢,好些没有],码迷,mamicode.com

让js中的函数只有一次有效调用的三种常用方法

如何让js中的函数只被有效执行一次,请看下面的三种常用方法. 1. <script> window.onload = function () { function once(fn) { var result; return function() { if(fn) { result = fn.apply(this, arguments); fn = null; } return result; }; } var callOnce = once(function() { console.log('

JS中的函数、Bom、DOM及JS事件

本期博主给大家带来JS的函数.Bom.DOM操作,以及JS各种常用的数据类型的相关知识,同时,这也是JavaScript极其重要的部分,博主将详细介绍各种属性的用法和方法. 一.JS中的函数 [函数的声明及调用] 1.函数声明的格式: function 函数名(参数1,参数2,参数3,--){//函数体 return 结果; } >>>函数的调用格式: 直接调用:函数调用的格式:函数名(参数一的值,参数二的值,--): 事件调用:事件名=函数名( ); 2.函数声明的几点强调: ①函数名

前端学习 第六弹: javascript中的函数与闭包

前端学习 第六弹:  javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) {    var tmp = 3;    function bar(y) {        alert(x + y + (++tmp));    }    bar(10);}foo(2) 这时无论怎么运行输出的都是16,但这不是闭包 如果我们返回内部函数,内部function会close-over外部fu

js中声明函数的区别

在JS中有两种定义函数的方式, 1是var aaa=function(){...} 2是function aaa(){...} var 方式定义的函数,不能先调用函数,后声明,只能先声明函数,然后调用. function方式定义函数可以先调用,后声明.请看代码: var声明时,只有变量声明提前了,变量的初始化代码仍在原位置.然而,使用函数声明的话,函数名称和函数体都会提前.两种声明得到的函数都不可删除 //aaa();这样调用就会出错                var aaa = funct

js中没有函数重载,怎样实现函数重载的功能?

js中没有函数重载,javasript中使用可选参数:arguments实现相同的功能.. 函数在定义的时候可不定义参数: <script type="text/javascript" > function say() { for (var i = 0; i < arguments.length; i++) { alert(arguments[i].toString()); } } </script> 调用:<input type="but

js中的函数,Date对象,Math对象和数组对象

函数就是完成某个功能的一组语句,js中的函数由关键字 function + 函数名 + 一组参数定义;函数在定义后可以被重复调用,通常将常用的功能写成一个函数,利用函数可以使代码的组织结构更多清晰. 其语法结构为 function funName (arg0, arg1, … argN){        //statements    } function say_hello (name, msg){ alert(“hello”+ name + “:”+ msg); } say_hello(“d

js中的函数function

js的function对象在调用过程中具有一个arguments的属性,它是由脚本解释器创建的(这也是arguments创建的唯一方式).arguments属性可以看作是一个Array对象,它有length属性,可以通过序号访问每一个参数,而且通过argument的callee属性可以获取对正在执行的Function对象的引用.如下: function factorial(n){ if(n<=n){ return 1; }else{ return n*arguments.callee(n-1);