手机版

谈谈JavaScript中的函数和闭包

时间:2021-11-21 来源:互联网 编辑:宝哥软件园 浏览:

很难说结束,也不难说。我将以我自己的理解来谈论闭包。1.闭包的解释对于函数式语言,函数可以保存内部数据状态。对于像C#这样的编译命令式语言,因为代码总是在代码段中执行,并且代码段是只读的,所以函数中的数据只能是静态数据。函数内部的局部变量存储在堆栈上,占用的堆栈在函数执行后释放,因此局部变量无法保存。采用Javascript作用域,函数的执行依赖于变量作用域,变量作用域是在定义函数时确定的。因此,Javascript中的函数对象不仅保存了代码逻辑,还必须引用当前的范围链。Javascript中函数内部的局部变量是可以修改的,当它们再次进入函数时,最后修改的状态会继续。这是因为局部变量不是保存在堆栈上,而是通过对象保存的。由范围链决定使用哪个变量。每次生成函数实例时,都会创建一个对象来保存局部变量,这个保存局部变量的对象将被添加到作用域链中。不同的函数对象可以通过范围链联系起来。Javascript中的所有函数都是闭包,所以我们无法避免“产生”闭包。解释请参考《Javascript高级程序设计》中的一个图,虽然这个图没有完全解释所有的情况。图中的激活对象是用于保存变量的对象。

简而言之,在Javascript: closure中:函数实例保存了执行过程中需要的变量的引用,但当时并没有复制和保存变量的值。(在Object C的实现中,我们可以选择保存当前值或者引用它。)当作用域链:解析变量时,它会找到变量所在的路径,并将var作为终止符号。如果链中没有var,它将返回到全局对象。C#中的闭包特性是通过编译器将局部变量转换成引用类型的对象成员来实现的。第二,使用闭包。这里有一些具体的例子来说明如何使用闭包:1。闭包是function Foo(){ function a(){ } function b(){ } function c(){ } }。每次我们执行Foo(),都有三个函数实例(闭包)。让我们验证在定义函数时确定了作用域链,因此它应该是‘局部作用域’varscope=‘全局作用域’;function check scope(){ var scope=' local scope ';函数f() {返回范围;}返回f;}checkscope()()的道理是一样的:(function(){ function a(){ } function b(){ } function c(){ }))执行完上面的表达式后,会生成三个函数实例(闭包),分别是a、b、c,因为是匿名函数,要立即执行,这三个闭包只能生成一次。生成的闭包没有其他引用,所以它将作为垃圾被销毁(不一定是立即销毁)。我们写这个的原因有两个:1。避免污染全局对象;2.避免多次生成相同的函数实例。对比下面两个例子,闭包是如何保存作用域链的:函数A(){} //与节省内存的写法相比,创建开销小的对象(函数(prototype){ var name='a ')速度快;函数SayName(){ alert(name);} function ChangeName(){ name=' _ changed ' } prototype . SayName=SayName;//引用执行匿名函数生成的闭包,闭包只会生成原型。changename=changename一次;}(A . prototype))var a1=new A();var a2=新A();a1 . SayName();a1 . changename();a2 . SayName();- .var名称=' b函数SayName(){ alert(name);} function changeName(){ name=' _ changed ';} this.sayName=sayName//引用闭包,每次调用函数b都会生成一个新的闭包this.changeName=changeName}//如果函数调用之前有new关键字,则该函数用作构造函数。//本质上,作为构造函数调用和作为普通函数调用没有区别。如果直接调用b(),这个对象将绑定到全局对象,新生成的闭包将被分配给全局对象的changeName和sayName属性,而不是旧的闭包,因此旧的闭包将被视为垃圾回收。//如果用作构造函数,new关键字将生成一个新对象(这指向这个新对象)并初始化这个新对象的sayName和changeName属性,因此每次生成的闭包都会因为引用而被保留。var b1=新B();B1 . SayName();B1 . changename();B1 . SayName();var b2=新B();B2 . SayName();B1 . SayName();3.泄漏问题:在编译语言中,函数体总是在文件的代码段,在运行时被加载到标记为可执行的内存区域。事实上,我们并不认为函数本身有生命周期。在大多数情况下,我们认为“引用类型数据结构”存在生命周期和泄漏的问题,例如指针和对象。实质上,JavaScript中的内存泄漏意味着保存定义函数时生成的局部变量的对象不会因为引用而被回收为垃圾。1.有循环引用。2.有些对象是不能销毁的,比如IE6的内存在DOM中泄露,或者Javascript引擎在销毁时不能得到通知,所以有些Javascript闭包是不能销毁的。

这些情况通常是由于Javascript宿主对象和Javascript中的本机对象之间的通信不良造成的。

版权声明:谈谈JavaScript中的函数和闭包是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。