JavaScript必知必会(九)function说起闭包问题_javascript技巧_第1页
JavaScript必知必会(九)function说起闭包问题_javascript技巧_第2页
JavaScript必知必会(九)function说起闭包问题_javascript技巧_第3页
JavaScript必知必会(九)function说起闭包问题_javascript技巧_第4页
JavaScript必知必会(九)function说起闭包问题_javascript技巧_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、javascript 必知必会(九)function 说 起闭包问题function函数格式function getprototynames (o, aoptionalv a)a 二 a | | ;for (var p in o)a. push(p);return a;callerfunc. caller返冋函数调用者function cal 1func()if(callfunc.caller)alert (callfunc. caller. tostring(); el sealert c没冇函数调用);function handlecaller()callfunc ();handlecal

2、ler() ;/返冋 handlercallfunc();/没有函数调用,返回null,执行了没有函数调用callee匿名方法递归调用alert ( (function (x) if (x 二)return ;return x * arguments. cal 1ee(x - );();/scope作用域大家都不陌生,今天就来说说闭包问题,深刻吃透闭包问题。<script>var global二"global scope"/这个是全局的作用域 function scope ()var scope = "local scope"/这个是局部的作

3、用域 return scope;/返冋的scope,是局部的变量</script>1、:定义的全局变量也能在函数内部访问。当定义的局部变量和全局变量 名字和同时,局部变量的就会隐藏全局变量,不会破坏全局变量的值。var scope 二"global scope"function f()var scope = /zlocal scope"return scope;alert (f();/local scopealert (scope);/global scope;上面确实是很容易理解,对吧。2、全局变量可以不用var声明,但是局部变量必须使用var声明,

4、如果局部变量不使用var声明,编译器会默认这个是个全局变量。<span style二line-height: ; font-family: verdana, arial, helvetica, sans-serif; font-size: px; background-color: rgb(, , ); </span> scope 二"global scope"function f() scope = "local scope"return scope;alert(f();/local scope alert (scope);/ioca

5、l scope但是全局变量不使用vh声明,也仅限非严格模式,如果使用严格模式的话, 会报错谋<script>use strict"scope 二"global scope"function f()scope = /zlocal scope"return scope;alert (f();/local scope alert (scope);/local scope </script>ii ie 丄i 丄: console0<top frame >preserve logo uncsught eferenceerrcr:

6、 scope is nor cefined所以建议大家声明变量时,千万不要省略可以避免不必要的麻烦。3、声明提前,也是可以滴。什么叫什么捉前。 line 17r column 1console0<top frame> _j preserve logundefined global scope<script>use strict" scope; console, log(scope);var scope 二"global scope" console, log (scope);</script>这个可能大家看出第一个打印undef

7、ined ,是呀述没有给他赋值,下而赋值可 定打e卩 global scope 了。这样理解并没有错,但是为什么会这样的呢,一个变量不是应该先定义才可以使 用的吗?这里给大家说下作用域链,javascript是基于词法作用域的语言。1、作用域链是一个对象或者链表,这组代码小定义了这段代码作用域小“的变 量。当javascript需要查找变量scope时,就会从链中的第一个对象开发查找, 如果第一个对象为scope,则会直接返回这个对象的值,如果不存在继续第二对 象开始查找,一直到找到。如果在作用域链上未查到该变量,则会抛岀一个错误。我们口j以这个作用链口j以这样表示:查找scope-windo

8、w (全局对象)很显然后 面是有定义scope的。但是并没有做赋值操作,后面才做赋值操作,所以此时值 为 undefined4、这个比较具有迷惑性了,大家猜想下打卬的值是什么?<script>"use strict"var scope = "global scope"function f() console 1og(scope);var scope = "local scope"consolc. log(scope);f();</script>看到这段代码:如果你粗心大意的话,很有可能会写出错谋的答案:1、go

9、bal scope2、local scope分析:声明了全局变量,在函数体中时,第一个表示全局变量,所以打卬global, 第二定义了局部的变量,覆盖掉了全局的scope,所以打印local scope。这样的分析在c# java ,完全正确。但是这里分析确实错误的。这说明这个问题前,我们先看一个问题。这句话很重要:全局变量在程序屮始终都是有定义的。局部变量在声明它的函数 体以及其所嵌套的函数内始终是定义的。如果你是从事高级语言工作开始接触javascript有点不适应其作用域的定义。 我也是这样的。我们來看一个例了:<script>var g 二"global scop

10、e"function f()for(var i=;i<i+)for (var j=;j<j+)console, log(j);con sole, log(i);console, log(g);f();</script>打印的结果是什么?大家看到表示语句块,语句块在一块作用域,所以大家可能猜想,j、i值已 经在内存释放掉了,所以结果肯定是undefined.真实的结果可能令你失望, line 29. column 8结果为什么会是这样,我开始的表情和你一样。这时查看我让你记住的那句话。全局变量在程序屮始终都是冇定义的。局部 变量在声明它的函数体以及其所嵌套的函数

11、内始终是定义的。确切的说函数的参数 也是属于局部变量的范畴。这句话也很重要! ! !那句话人概意思说,只要是在函数内部定义的变量,在整个函数内都是有效的。 所以结果也就不难理解了。在回过头看我们的那个问题,你理解了吗?作用链还有以下定义:1、作用链是有一个全局对彖组成。2、在不包含嵌套的函数体内,作用链上有两个对象,第一个定义了函数参数和 局部变量的对象,第二个是全局对象。3、在一个欧套的函数体内,作用链上至少包含三个对象。当定以一个函数的时候,就会保存一个作用域链。当调用这个函数时,它就会创建一个新的对象來存储它的局部变量,并将这个对 象添加到保存的作用链上。同时创建一个新的更长的表示函数调

12、用的作用链。对于嵌套的函数,当调用外部函数时,内部函数又会重新定义一遍。因为每次调 用外部函数的时候,作用链都是不同的。内部函数在每次定义的时候都有微妙的 差别,每次调用的外部函数时,内部函数的代码都是相同的,而且关联的代码的 作用域也是不同的。闭包 搞了这么久终于要讲了,但是再将z前我们在來分析下作用域。<script>var nameg=zzglobal,zvar g 二 function f() console, log(name);function demo()console. log(z/demo=z/+name); var name =;function demo()

13、var name 二;console. log(demo二 + name);function demo() console, log(deino二 + nameg);demo();demo ();demo ();go;</script>我们按照作用链來分析:调用demoo, demoo ()->查找name,未找到->f ()查找,返回调用demol, demol () -查找name,找到,返冋调用 demo2, demo2 () -查找 nameg,未找到-f ()查找 nameg,未找到->window 查 找nameg找到,返回。看这个例子:<scr

14、ipt> function f()var count 二;return counter:function() return count+;,reset: fun cti on ()rcturn count =;var d 二 f ();var c 二 f ();console. log(,zd 第一次调用:"+ d. counter () ;/console. log(z,c 第一次调用:"+ c. counter () ;/ 互不影响console. log(,zd 第一次调用:+ d. reset () ;/console. log(c 第二次调调用 + c. c

15、ounter () ;/ </script>这个例子上大家可以看到,我做了一个计数和置零的操作。创建了两个f的对彖实例d c,各冇自己的作用威链,所以其值互不影响。当c 笫二次调用时,count值被保存了,因为c对彖并未被销毁。明口这个例子后, 后面的例子才比较好懂。这个过程,大家应该十分明了了。那么现在我们来看闭包问题。我设置四个按钮, 点击每个按钮就返回响应的名字。<body><script>function btnlnit()for(var i二;i<i+)var bln 二 document. getelementbyid(bt+ i); bt

16、n.addeventlistener("click", function() alert c,btn/,+ i););window. onload二 btnlnit;</script><div><button id=,zbtn,>btn</button><button id二btn>btn</button>button id二btrt>btn/button><button id=,btn/,>btn</button></div></body>点

17、击运行,结果却是都是btn5;我们用刚才的分析在处下,首先要调用匿名函数->查找i,未找到->btntnit(), 找到i在for循环中。找到。我们知道只冇函数调用结束才释放,for中的i总 是可见的,所以保留了最后的i值。那么如何解决呢。解决i值在函数屮不是总是可见的,那么我们就要使用函数的嵌套了,然后把i 值传进去。function btnlnit()for(var i=;i<i+)(function (dala_i) var btn 二 documentgetelementbyid("bt+ data_i);btnaddevcntlistcncr("

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论