javascript函数及闭包详解

1.arguments[]对象在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。还可以用 arguments 对象检测函数的参数个数,引用属性 arguments.length

2function对象的length属性ECMAScript 定义的属性 length 声明了函数期望的参数个数

3Function 对象也有与所有对象共享的 valueOf() 方法和 toString() 方法。这两个方法返回的都是函数的源代码,在调试时尤其有用

4闭包:

什么时候需要用到闭包:
1.需要在一个函数外部,访问函数内部的变量的时候(也就是说在函数运行完之后,你想要把变量保存下来,待需要的时候调用。而不是通过垃圾回收机制消除(garbage collection))。
2.保护变量安全。一个函数的内部变量,只能内部函数引用。

如何定义闭包:在一个函数内部,定义一个函数,并返回一个函数的引用。

3. 先看下闭包的两种形式:

//第一种形式:

function outer(){
       var i = 7;

function inner(){

alert(i);

}

inner();    //可以用setInteval(inner,5000);实现每5秒执行一次inner函数

}

//第二种形式:

function outer(){

var i = 7;

function inner(){

alert(i);

}

return inner(); //函数是一种特殊的对象, 这里直接返回函数的引用

}

var f = outer();       //使用f接受返回的内层函数的引用

f();  //调用内层函数

在第一种情况时: outer函数定义局部变量i, 函数inner(), 之后又调用了inner函数. 注意看inner()函数,
inner函数中 并没有定义变量i, 这个i是来自于outer函数的局部变量. 当在inner函数被引用的时候,
由于内层的inner函数需要使用变量i, 因此这个运行时定义的变量i不能被释放, 从而在inner()函数执行时就可以取得这个变量的值.

当第二种情况时: 执行outer()函数之后, 将返回inner()函数的引用, 由于外部变量f引用了内部函数inner(),
由于inner()函数同样需要使用变量i, 这个局部变量i也将被外部变量f所引用, 因此变量i依然不能被释放. 与第一种形式的区别是:
我们可以再outer()函数执行之后访问到变量i的值. 如果我们将alert(i); 改成 alert(++i); 那么在函数的外部, 我们执行f(); 此时变量i并没有释放, 结果应该是8,
如果再调用一次f(); 则结果变成9。但是: 如果我们再次调用outer();函数后将会创建一个新的局部变量, 之后再调用f();
结果则变成了8. 也就是说只要外层函数没有再次创建新变量, 原来的变量i将一直有效.

4闭包可以用在许多地方。它的最大用处有两个,个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

怎么来理解这句话呢?请看下面的代码。

Js代码

  function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个

匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

4闭包的注意点:

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

5闭包的应用场景
保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。

  1. 在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。
  2. 通过保护变量的安全实现JS私有属性和私有方法(不能被外部访问)
    私有属性和方法在Constructor外是无法被访问的

    function Constructor(...) {  
      var that = this;  
      var membername = value; 
      function membername(...) {...}
    }

以上3点是闭包最基本的应用场景,很多经典案例都源于此。

6Javascript的垃圾回收机制

在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

时间: 2024-10-10 01:13:00

javascript函数及闭包详解的相关文章

javascript系列2 -- 闭包详解

转发请标明来源:http://www.cnblogs.com/johnhou/p/javascript.html  请尊重笔者的劳动成果  --John Hou 今天我们从内存结构上来讲解下 javascript中的闭包概念. 闭包:是指有权访问另外一个函数作用域中的变量的函数.创建闭包的常见方式就是在一个函数内部创建另外一个函数. 在javascript中没有块级作用域,一般为了给某个函数申明一些只有该函数才能使用的局部变量时,我们就会用到闭包,这样我们可以很大程度上减少全局作用域中的变量,净

JavaScript中的闭包详解

闭包是JavaScript的重要特性,非常强大,可用于执行复杂的计算,可并不容易理解,尤其是对之前从事面向对象编程的人来说,对 JavaScript 认识和编程显得更难.特别是在看一些开源的JavaScript代码时感觉尤其如此,跟看天书没什么区别. 一般情况下,人们认识一个事物,会根据之前的经验,进行对比和总结,在脑中建立一个模型,从而理解掌握它,但是JavaScript与面向对象编程实在"没有可比性",最明显的是某过于写法,总觉得"怪怪的",更不用说,其一些高级

javascript 用函数语句和表达式定义函数的区别详解

通常我们会看到以下两种定义函数的方式: // 函数语句 function fn(str) { console.log(str); }; // 表达式定义 var fnx=function(str) { console.log(str+ ' from fnx'); }; 两种方式都创建了新的函数对象, 但函数声明语句的函数名是一个变量名, 变量指向函数对象, 和通过var声明变量一样,函数定义语句中的函数被显示地提前到了脚本或函数的顶部, 因此它们在整个脚本和函数内都是可见的,但是使用var 表达

【JavaScript中的this详解】

前言 this用法说难不难,有时候函数调用时,往往会搞不清楚this指向谁?那么,关于this的用法,你知道多少呢? 下面我来给大家整理一下关于this的详细分析,希望对大家有所帮助! this指向的规律 this指向的规律往往与函数调用的方式息息相关:this指向的情况,取决于函数调用的方法有哪些. 我们来看一下姜浩五大定律: 姜浩五大定律: ①通过函数名()直接调用:this指向window: ②通过对象.函数名()调用的:this指向这个对象: ③函数作为数组的一个元素,通过数组下标调用的

setAttribute()函数的用法详解

setAttribute()函数的用法详解:在动态创建元素设置元素的属性的时候setAttribute()函数用处很大,它可以动态的设置元素的属性,下面介绍一下它的用法.语法结构: setAttribute(name, value) 1).name表示要设置的属性.2).value表示属性值.代码实例如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta nam

javascript AJAX与Comet详解

          博客专家福利      [限时活动]建专辑得大奖       专访荣浩:流程的永恒之道      当青春遇上互联网,能否点燃你的创业梦      推荐有礼--找出您心中的技术大牛 javascript AJAX与Comet详解 分类: javascript2012-12-24 17:39 367人阅读 评论(0) 收藏 举报 XMLHttpRequest对象 在IE5中,XHR对象是通过MSXML库中的ActiveX对象实现的.在IE中可能会遇到三种不同版本的XHR对象,即M

JavaScript 开发规范要求详解

作为一名开发人员(We前端JavaScript开发),不规范的开发不仅使日后代码维护变的困难,同时也不利于团队的合作,通常还会带来代码安全以及执行效率上的问题.本人在开发工作中就曾与不按规范来开发的同事合作过,与他合作就不能用"愉快"来形容了.现在本人撰写此文的目的除了与大家分享一点点经验外,更多的是希望对未来的合作伙伴能够起到一定的借鉴作用.当然,如果我说的有不科学的地方还希望各路前辈多多指教.下面分条目列出各种规范要求,这些要求都是针对同事编码毛病提出来的,好些行业约定的其它规范可

jQuery的next()函数的使用详解

jQuery的next()函数的使用详解:此函数在代码中有大量的应用,下面就结合实例介绍一下此函数的用法.它可以取得一个包含匹配元素集合中每一个元素紧邻的后面同辈元素的元素集合.在上面的概念中有下面几点需要特别注意:1."紧邻",也就是说获取的元素必须是匹配元素所紧邻的,中间不能够有其他的元素间隔.2."同辈",也就是说获取的元素必须和匹配是同级元素.3."后面",也就是i说获取的元素必须位于匹配元素的后面.语法结构: $(selector).n

Javascript 异步加载详解(转)

本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续