-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
什么是闭包?闭包的作用是什么? #24
Comments
first, 沙发沙发切入正题,闭包,可以理解为作用域链的延伸;通过自执行函数将函数作用域变量通过api的方式暴露出来,这种方式并不会创建全局变量,这种操作既可以访问局部变量,同时还限制了变量的复写,大部分模块都是基于此实现,由局部变量与外部获取共同构成了闭包。理解浅显,还请大佬指正. |
闭包: |
闭包是什么?闭包有三步: 第一,外层函数嵌套内层函数; 第二, 内层函数使用外层函数的局部变量; 第三,把内层函数作为外层函数的返回值! 经过这样的三步就可以形成一个闭包! 闭包就可以在全局函数里面操作另一个作用域的局部变量! 闭包的作用?闭包既能重复使用局部变量,又不污染全局! |
闭包是有权访问另一个函数作用域中的变量的函数:当函数1向外暴露了可以改变内部局部变量的方法(内部匿名函数,外部函数2接受匿名函数,匿名函数作用域链在初始化时包含了函数1的变量对象,可以调用函数1所有的内部变量。一般函数执行完局部活动对象就会进行销毁,内存仅仅只会保存全局作用域,但函数1在执行完毕其活动对象也不会进行销毁,因为匿名函数的作用域链仍然在对其进行调用。(参考高程 |
js采用的是词法作用域,也就是函数可以访问的变量在函数定义时写在哪里就确定了和函数被调用的位置无关。闭包就是函数不在定义的词法作用域内被调用,但是仍然可以访问词法作用域中定义的变量。 闭包可以被用在三个地方:
// name 只能通过getName接口来访问
function Person(name) {
this.getName = function() {
return name;
}
}
function module() {
let inner = 1;
let increaseInner = function() {
inner++;
}
let decreaseInner = function() {
inner--;
}
let getInner = function() {
return inner;
}
return {
increaseInner,
decreaseInner,
getInner
}
}
let api = module();
console.log(api.getInner());
api.increaseInner();
console.log(api.getInner());
api.decreaseInner();
console.log(api.getInner());
for (var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
console.log(i)
}, 1000);
})(i);
} |
当内部函数被保存到外部时,就会形成闭包;
|
从定义上讲 : 闭包其实是一个绑定了执行环境的函数,所以广义的闭包其实就对应了JS中的函数。 它的执行环境是函数词法环境,由环境记录器和作用域链组成。 而通常我们所讲的闭包是在一个函数 A 内部有一个函数 B,通过函数 B 记录访问函数 A 内的变量。 因为作用域的关系,函数A外部无法直接访问内部数据,而通过闭包这种方法可以让我们可以间接访问 函数内部的私有变量,利用这一特性我们可以用来封装私有变量,实现数据寄存等 |
闭包就是有权在一个函数去访问另一个函数的变量。通常是在一个函数内部创建一个函数。 |
我理解的闭包是:一个函数在另外一个函数中,这个内部函数使用外部函数的局部变量,并且内部函数被所在函数以外的地方调用。这个内部函数就被称为闭包。 |
红宝书里面说:“闭包就是指有权访问另一个函数作用域中的变量的函数“。 只要存在调用内部函数的可能,js就需要保存被引用的函数。js运行时需要跟踪引用到的这个内部函数的所有变量,一直到最后一个变量废除,js的GC才能回收这些变量的内存空间。作用:
|
要理解闭包,必须了解JS特殊的变量作用域。
另一方面,在函数外部无法读取函数内的局部变量。
我们有时候需要得到函数内的局部变量,那要怎么办呢?
上面的函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来不行,f2内部的局部变量,对f1是不可见的。这就是JS语言特有的链式作用域结构,子对象会一级一级地向上寻找所有父对象的变量。 既然f2可以读取f1中的局部变量,只要把f2作为返回值返回,在f1内部就可以读取它的内部变量了。
闭包的概念
参考连接: |
什么是闭包?因为js作用域的问题,函数内部可以访问函数外部的变量,而函数外部不能访问函数内部的变量,有时我们需要访问函数内部的变量,这就需要在函数内部返回一个函数,返回需要访问的变量。这就是闭包。 闭包的作用1、属性私有化 |
什么是闭包? |
闭包定义:当函数可以记住并访问所在的词法作用域,就产生了闭包。即使函数是在当前词法作用域之外执行。 简单来说就是:
缺陷:
作用
// IIFE的目的是为了隔离作用域,防止污染全局命名空间。
(function() {
//这里是块级作用域
})();
|
闭包问题定义你不知道的js 书是这样定义的:当函数可以记住并访问所在的词法作用域时就产生的了闭包,即使函数是在当前词法作用域之外执行。
bar 能使foo的内部作用域不会在foo()执行后立即被销毁,会一直存活,以便bar() 后续进行使用。 |
讲个故事:一对情侣去酒店开房!到了晚上要做就要做该做的事情,嘿嘿嘿的那种。门房禁闭。窗户窗帘拉上,从外面绝对看不到房间内状况。但是万恶的酒店老板是在房间内装了隐形摄像头(闭包)...老板通过摄像头能清楚的看到大战状况... |
JavaScript采用词法作用域,即函数能访问的作用域是定义它的时候就决定了. 作用:
|
1. 闭包的定义
2.闭包的应用用闭包解决递归问题
用闭包模仿块级作用域
封装私有变量
在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。 3.闭包的作用
4.闭包的注意事项通常,函数的作用域及其所有变量都会在函数执行结束后被销毁,被垃圾回收机制回收。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。
闭包只能取得包含函数中任何变量的最后一个值,这是因为闭包所保存的是整个变量对象,而不是某个特殊的变量。
闭包中的this
5.闭包的缺点
6.关于闭包的面试题第一个JS闭包问题
(1)先确定这三个函数的关系 这段代码中出现了三个fun函数,所以第一步先搞清楚,这三个fun函数的关系,哪个函数与哪个函数是相同的。
先看第一个fun函数,属于标准具名函数声明,是新创建的函数,他的返回值是一个对象字面量表达式,属于一个新的object。这个新的对象内部包含一个也叫fun的属性,通过上述介绍可得知,属于匿名函数表达式,即fun这个属性中存放的是一个新创建匿名函数表达式。 注意:所有声明的匿名函数都是一个新函数。 所以第一个fun函数与第二个fun函数不相同,均为新创建的函数。最内层的return出去的fun函数不是第二层fun函数,是最外层的fun函数。所以,三个fun函数的关系也理清楚了,第一个等于第三个,他们都不等于第二个。 (2)函数是怎样调用的 为了方便看把代码重新写一下
第一行 a
第一个fun(0)是在调用第一层fun函数。第二个fun(1)是在调用前一个fun的返回值的fun函数,所以:第后面几个fun(1),fun(2),fun(3),函数都是在调用第二层fun函数。 遂:
即:最终答案为 undefined,0,0,0 第二行 b
先从fun(0)开始看,肯定是调用的第一层fun函数;而他的返回值是一个对象,所以第二个fun(1)调用的是第二层fun函数,后面几个也是调用的第二层fun函数。 遂:
即最终答案:undefined,0,1,2 第三行 c
根据前面两个例子,可以得知: fun(0)为执行第一层fun函数,.fun(1)执行的是fun(0)返回的第二层fun函数,这里语句结束,遂c存放的是fun(1)的返回值,而不是fun(0)的返回值,所以c中闭包的也是fun(1)第二次执行的n的值。c.fun(2)执行的是fun(1)返回的第二层fun函数,c.fun(3)执行的也是fun(1)返回的第二层fun函数。 遂:
即最终答案:undefined,0,1,1 第二个JS闭包问题循环中使用闭包解决 var 定义函数的问题
首先因为 setTimeout 是个异步函数,所有会先把循环全部执行完毕,这时候 i就是 6 了,所以会输出一堆 6。 解决办法两种,第一种使用闭包
第二种就是使用 setTimeout 的第三个参数
第三种就是使用 let 定义 i 了
因为对于 let 来说,他会创建一个块级作用域,相当于
|
借用《你不知道的javascript》上的一句话:当函数可以记住并访问其所在的词法作用域,即使该函数在其词法作用域之外执行,这时就产生了闭包。 |
闭包是什么?闭包就是有权访问另一个函数作用域中的变量的函数。 闭包的作用?
|
什么是闭包?
闭包是由函数以及创建该函数的词法环境组合而成。这个环境包含了这个闭包创建时所能访问的所有局部变量。
闭包的作用是什么?模拟私有方法,定义公共函数(模块模式),以及上例中的函数工厂。使用闭包可以实现这些功能,这样回答闭包的作用不知道是否恰当。楼上同学对于作用的回答可能更合适一些。 性能考量如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响。
在上面的代码中,我们并没有利用到闭包的好处,因此可以避免使用闭包。修改成如下:
但我们不建议重新定义原型。可改成如下例子:
以上都是来自MDN的砖块打造,更加详细的内容欢迎同学们去看MDN闭包的文档。 虽然有人说答题不是复制粘贴一下文档就完事了,不过想了想还是把MDN给的示例搬了过来,因为他真的不错。(菜鸡瑟瑟发抖.png) |
什么是闭包?闭包的作用是什么?什么是闭包Closure是函数有能力记住和访问变量的词法作用域, 在函数本身已经执行完成后。(数据持久性) 闭包出现的原因由于js引擎的垃圾回收机制, 在执行我们的代码的时候,js维护着一个调用栈。在函数执行完成的时候,由垃圾回收机制去处理这个调用栈(调用栈内包含函数的词法作用域), 要销毁调用栈的时候,发现还存在引用。那么垃圾回机制就不处理它。这就导致这个函数的词法作用域保留了下来,也让该函数具有了数据持久性。有利也有弊,基于垃圾回收机制,如果你的闭包内存有大量数据, 那么它是不会被清除的, 这就需要我们自己手动的去处理它。 闭包的作用
console.log('方案3: setTimeout内闭包');
for (let i = 0; i <= 3; i++) {
setTimeout(((i) => {
return () => {
console.log(i);
}
})(i), i * 1000);
}
const addOperator = x => y => x + y;
const add1Operator = addOperator(1);
const add2Operator = addOperator(2);
add1Operator(1); // 2
add2Operator(1); // 3 |
我敬你是个人才~~~ |
什么是闭包?闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包最常用的方式就是在一个函数内部创建另一个函数。 闭包的作用
function base() {
let x = 10;
return {
count: function() {
return x++;
}
}
}
let obj = base();
console.log(obj.count()); //11
console.log(obj.count()); //12
console.log(obj.count()); //13
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = (function(j){
return function () {
console.log(j);
}
})(i)
}
a[6](); // 6 闭包的缺点闭包会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏 |
闭包(closure) 是指在一个函数有权访问另一个函数作用域中的变量的函数
闭包的作用
输出结果是10个10
我们没有直接将闭包返回给数组,而是定义了一个匿名函数,将立即执行的结果赋给了数组。这里的匿名函数有个一个参数num,也就是最终的函数要返回的值。在调用这个匿名函数时,我们传入变量i。由于时按值传递的,所以就会将变量i赋值给num,又创建了便返回num的闭包,这样一来,result数组里面的每个函数都有自己num变量的一个副本,所以能到我们预期的结果 |
|
闭包: 外部作用域访问内部作用域变量的方法。 |
闭包的概念闭包是指有权访问另一个 函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。 闭包的作用
闭包的应用场景
function bind(fn, context){
return function(){
return fn.apply(context, arguments);
};
} 在 bind()中创建了一个闭包,闭包使用 apply()调 用传入的函数,并给 apply()传递 context 对象和参数。注意这里使用的 arguments 对象是内部函 数的,而非 bind()的。当调用返回的函数时,它会在给定环境中执行被传入的函数并给出所有参数。
function curry(fn){
var args = Array.prototype.slice.call(arguments, 1);
return function(){
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
};
} 使用闭包的注意事项由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,在绝对必要的情况下再考虑使用闭包。虽然像 V8 等优化后的 JavaScript 引擎会尝试回收被闭包占用的内存,但是闭包还是要慎重使用。 |
闭包指的是能够访问另一作用域的值的能力,常见的闭包就是在一个函数内部创建另一个函数。 |
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数在所在词法作用域外执行。 |
### 闭包是将函数内部和函数外部连接起来的桥梁。 ### 作用: |
闭包:闭包就是能够读取其他函数内部变量的函数。在JS中,只有在函数内部的子函数才能读取局部变量,因此可以简单理解成“定义在函数内部的函数”,所以在本质上:闭包就是将函数内部和函数外部连接起来的一个桥梁。 闭包的作用
2、实现模块化
3、模拟块级作用域
|
闭包:闭包就是能够取其他函数内部的变量,在js中,只有在函数内部的子函数才能读取局部变量,因此可以理解成定义函数内部的函数,所以本质上,就是连接内部和外部的桥梁, 闭包的作用: 1.封装私有变量
} 2.实现模块化 function mank() { 3.模拟块级作用域 总结:闭可能会造成内存的泄露,但还是很长用 |
闭包 闭包的作用 闭包的场景 闭包的例子
} var a2 = fn.addnum() var a3 = fn.addnum() console.log(a1,a2,a3) // 2,3,4 for(var i=1;i<10;i++){
} |
什么是闭包?闭包的作用是什么###为了保护数据能被获得但不会被改变的这种场景,比如:
###可以封装模块 ###实现块级作用域(类似于let)
解决方案一:
解决方案二:
闭包的确定内存泄漏 |
什么是闭包?闭包是指在一个函数有权访问另一个函数作用域中的变量的函数。、 闭包的作用是什么?能够获取其他函数内部的变量 |
闭包: (微信名:RUN) |
我认同圣经里说的,因为闭包并不是JavaScript的概念,JavaScript标准里从来没提过闭包。从闭包的古典定义里(带有一系列信息的λ表达式)可以发现闭包就是带了执行环境的函数。而JavaScript中函数正好复合这个定义,它的环境部分就是函数的词法作用域 |
No description provided.
The text was updated successfully, but these errors were encountered: