js中闭包问题

http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651551586&idx=1&sn=56553b4a7af46e3fc5204a2294c3299d&chksm=8025a0a3b75229b56ff1b978b7871f4022db43917b6ad8166e62f5423935b520075b08b2abae&mpshare=1&scene=23&srcid=12220aU9OUg3IsXuT2rDTaAP#rd

其实关于闭包各个论坛社区里都有很多的文章来讲它,毕竟闭包是JavaScript中一个特色,也正因为这个雨中不同的特色也让闭包理解起来有一些吃力。笔者在这里不仅仅是想介绍闭包,也向列举一些笔者所见过的一些闭包,如果有读者还有一些比较经典的闭包例子,希望可以在评论区里留一下,谢谢。


说了半天,究竟什么是闭包呢?


  • 闭包就是函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。

  • 闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。

  • 当在一个函数内定义另外一个函数就会产生闭包。


为了便于理解,我们可以简单的将闭包理解为:


  • 闭包:是指有权访问另外一个函数作用域中的变量的函数。


JavaScript中的作用域


JavaScript中是没有块级作用域的。不过关于块级作用域我们在这里不做深入探究,笔者在JavaScript的作用域和块级作用域概念理解中有对块级作用域较为详细的解释,不懂的读者可以去看看。


变量的作用域无非就是两种:全局变量和局部变量。


Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。


var n=999;

function f1(){

    alert(n);

}

f1(); // 999


如上函数,f1可调用全局变量n


另一方面,在函数外部自然无法读取函数内的局部变量。


function f1(){

    var n=999;

}

alert(n); // error


这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量。


function f1(){

    n=999;

}

f1();

alert(n); // 999


闭包


1.理解闭包


我们已经理解了什么是作用域,什么是块级作用域,那又该如何去访问函数内部的变量呢?


出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。


function f1(){

var n=999;

function f2(){

    alert(n);

}

    return f2;

}

var result=f1();

result();// 弹出999


上面函数中的f2函数就是闭包,就是通过建立函数来访问函数内部的局部变量。


2.闭包的用途


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


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,可以在函数外部对函数内部的局部变量进行操作。


3.闭包的注意点


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


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


4.经典闭包小案例


如果你能理解下面全部的案例,那你的闭包就算是真正掌握了。


var name = "The Window";

var object = {

name : "My Object",

getNameFunc : function(){

    return function(){

        return this.name;

        };

    }

};  alert(object.getNameFunc()());//The Window


var name = "The Window";

var object = {

name : "My Object",

getNameFunc : function(){

    var that = this;

    return function(){

        return that.name;

        };

    }

  };

  alert(object.getNameFunc()());//My Object


function fun(n,o) {

  console.log(o)

  return {

    fun:function(m){

      return fun(m,n);

    }

  };

}

var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?

var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?

var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?


//问:三行a,b,c的输出分别是什么?

这是一道非常典型的JS闭包问题。其中嵌套了三层fun函数,搞清楚每层fun的函数是那个fun函数尤为重要。


//答案:

//a: undefined,0,0,0


//b: undefined,0,1,2


//c: undefined,0,1,1

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值