Open haizhilin2013 opened 5 years ago
(fucntion(){
})()
function(){
var a = 0;
return function(){
return a++
}
}
上面就是闭包,有独立的作用域,且作用域的变量不会在程序中释放
closure:关闭 关闭变量或者说是隐藏一个变量 我们函数套函数其实相当于形成了一个局部作用域,就达到了隐藏的目的 仅此而已
闭包:在局部作用域引用上层作用域(非全局)的变量 优点:防止变量污染作用域 缺点:不释放则会导致内存泄漏
闭包是可以访问另一个函数作用域的函数。由于 javascript
的特性,外层的函数无法访问内部函数的变量;而内部函数可以访问外部函数的变量(即作用域链)。
function a(){
var b = 1;
var c = 2;
// 这个函数就是个闭包,可以访问外层 a 函数的变量
return function(){
var d = 3;
return b + c + d;
}
}
var e = a();
console.log(e());
因此,使用闭包可以隐藏变量以及防止变量被篡改和作用域的污染,从而实现封装。 而缺点就是由于保留了作用域链,会增加内存的开销。因此需要注意内存的使用,并且防止内存泄露的问题。
感谢大佬的分享,讲的十分透彻。
闭包的定义:从外部访问或者操作函数内部变量的的方式,缓存数据,延长作用域链(JS是函数作用域)
例子:定义了一个内部变量,但是不想使这些变量不能被外部随意修改,同时又可以通过指定的函数接口来操作来访问,闭包的作用常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」
缺点:函数中的变量不能及时的释放
function Foo(){
var name = "fooname"; //需要从外部访问这些变量
var age = 12;
this.getFoo = function(){ //设置访问方法
return name;
}
this.setFoo = function(){
return age;
}
this.xgFoo = function(new){
name = new;
}
}
var foo = new Foo();
foo.getFoo(); //访问name变量。
foo.xgFoo("liz") //从外部修改nage变量
当函数能够记住并访问所在的词法作用域,即使函数是在当时词法作用域之外执行,这是就产生了闭包。
词法作用域是变量或函数声明时,在词法解析阶段所在的作用域。
function foo() {
var a = 2;
function bar() {
console.log(a)
}
return bar
}
var baz = foo()
bar() // 2
a
和 bar
标识符。bar
函数的引用返回bar
函数词法作用域(foo) 之外调用。按理说 foo
函数调用完结束后就应该被销毁了。但是闭包能够让 bar
函数一直引用着它在词法阶段所在的作用域 foo
,这个引用就是闭包。所以可以正常访问变量 a
这个 bar 函数在定义的词法作用域以外的地方被调用。闭包使得函数能够继续访问定义时的词法作用域。
无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论何时执行这个函数都会使用闭包。
看黑体字: 函数wrapper_func内 返回一个函数inner_func, 外部通过inner_func可以访问wrapper_func函数内的变量(作用域链)。
函数返回函数,形成局部作用域
局部作用域,防止变量污染
内存泄露
命名空间/for循环取第i个处理为什么返回同一个i值(可以搜一下,老面试题了)
闭包是一个函数,这个函数可以访问另一个函数的变量。(当你创建一个函数时你就创建了一个闭包) 优点:由于闭包里可以访问外部变量,但是外部不能访问闭包里的变量,所以可以保护一些重要的不能被修改的变量。 缺点:在老IE6使用闭包可能会造成内存泄漏
闭包就是声明在函数内部的函数(或者是可以访问外部函数变量的函数) 优点:希望一个变量长期存储在内存中,避免全局变量的污染,私有成员的存在 缺点:会导致内存占量过高,容易造成内存泄露
函数中裹着函数就产生闭包,父函数访问子函数就是借用闭包的作用 子函数访问父函数就是顺着作用域链 有点类似vue框架的父能传参给子组件,而子组件只能this.emit才行
第14天 什么是闭包?优缺点分别是什么?
函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。
闭包:在局部作用域引用上层作用域(非全局)的变量 优点:防止变量污染作用域 缺点:不释放则会导致内存泄漏
从函数外部访问到函数内部的变量,函数内部的变量的作用域不会被释放,通常从函数内部返回一个函数。 缺点:会导致内存泄漏
简单说就是函数套函数,函数外部可以访问到内部的变量, 优点:防止全局变量污染 缺点:可能会导致内存泄漏(ie
当一个函数能够访问和操作另一个函数作用域中的变量时,就构成了一个闭包(closure)
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
//函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的
上面代码中的f2函数,就是闭包
由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数。
所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
要理解闭包,首先要理解JS的变量作用域。变量的作用域有两种:全局变量和局部变量。JS语言的特别之处在于:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。那么如何从外部读取函数内部的局部变量?可以在函数内部再定义一个函数,如下所示: 1.function f1(){ 2. var n=999; 3. function f2(){ 4. alert(n); // 999 5. } 6.} 在上面的代码中,函数f2被包含在函数f1内部,这时f1内部的局部变量对f2都是可见的。但是反过来就不行。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,就可以在f1外部读取其内部的变量,故而f2函数就是闭包。因此闭包可以理解为定义在一个函数内部的函数。 闭包的作用:可以读取函数内部的变量;让这些变量的值始终保持在内存中,不会自动清除。 注意点:由于闭包会使函数中的变量都被保存在内存中,内存消耗较大,所以不能滥用闭包,否则会造成网页的性能问题。解决方法是:在退出函数之前,将不使用的局部变量全部删除;闭包会在函数外部,改变夫函数内部变量的值。
要理解闭包,首先要理解javascript的特殊的变量作用域。 变量的作用域无非就两种:全局变量和局部变量。 优点:防止污染作用域 缺点:需要手动置null,不然会内存泄漏
作用域链:只能访问自身或外层作用域的变量。 闭包:可以访问函数内部变量的函数。 方式:在函数a中手动返回一个函数b,该函数b包含了函数a中的变量。
function a(){
let n = 1;
return () => n;
}
a()() // 可以获取到a函数中声明的变量n
作用:
闭包: 当一个函数能访问和操作另一个函数作用域的变量时,此时就形成了闭包 优点: 避免污染全局环境 缺点:由于外部可以访问到函数内部变量,因为函数执行完成后,函数没有被销毁,闭包过多会导致内存泄露。
一个函数可以访问另一个函数内的变量,当这个函数被运行时,就形成了一个闭包,因为这个变量因为被引用着,所以即使执行完毕了也不会被回收掉。
就是每一个函数都是一个闭包。
闭包是一个函数和它周围环境(词法环境)的引用的组合。
所以每一个函数可以形成一个闭包。
function outerFn(){
// 私有变量,outerFn函数外不能直接访问
var _name = 'private name';
// 私有函数,outerFn函数外不能直接访问
function _fn(){
console.log("trigger private function")
}
// 返回一个方法,以供外部可以访问到outerFn的私有变量、函数
return function(){ // 返回的这个函数,可以访问_name、_fn()
console.log(_name)
_fn();
}
}
let fn = outerFn();
fn();
html文件
<ul>
<li>xxxxxxxxxxx</li>
<li>xxxxxxxxxxx</li>
<li>xxxxxxxxxxx</li>
<li>xxxxxxxxxxx</li>
</ul>
var liElements = document.getElementsByTagName('li');
for(var i=0; i< liElements.length; i++){
liElements[i].onclick = function(){
console.log(i); // 因为 变量i 是公用一个词法环境,所以最终输出的都一样,都输出 4
}
}
可以用新的函数来隔开不同的i,使得获取的i在不同的词法环境
var liElements = document.getElementsByTagName('li');
for(var i=0; i< liElements.length; i++){
liElements[i].onclick = (function(i){ // 利用自执行匿名函数,给每一个元素的onclick事件分隔开了不同值的i
return function(){
console.log(i); // 分别输出 0、1、2、3
}
})(i)
}
var liElements = document.getElementsByTagName('li');
Array.prototype.forEach.call(liElements, function(item, i){ // 利用匿名函数,给每一个元素的onclick事件分隔开了不同值的i
liElements[i].onclick = function () {
console.log(i)
}
})
或者使用ES2015 引入的 let 关键词
var liElements = document.getElementsByTagName('li');
for (let i = 0; i < liElements.length; i++) {
liElements[i].onclick = function () {
console.log(i); // 分别输出 0、1、2、3
}
}
闭包就可以在全局函数里面操作另一个作用域的局部变量! 优点:私有变量 缺点:造成内存泄漏
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。 优点:可以通过闭包创建私有变量,并且不允许外界访问 缺点:消耗内存
第14天 什么是闭包?优缺点分别是什么?