javascript 近乎神话般的概念:闭包

但是第二次我们再执行result()的时候就出现了问题,为什么会是2呢?按照流程,首先再foo2()函数内部寻找count,没有然后到外层寻找,找到了count=0,这时候count+1应该为1才对.这里就涉及到闭包的问题了.

首先我们在原来的代码中加一个debugger,然后到谷歌浏览器右键检查,点击resources就可以看到右边有一个Closure,浏览器的可视化已经证实了这的确是一个闭包.并且count=1已经存储在了Closure之中.也就说明count=1没有被销毁,等下次在调用result()的时候count=2.

认识作用域

要学习Clusure必须了解JavaScript的作用域相关知识 作用域包括:

1.全局作用域

2.函数作用域

4.块级作用域(es6 新出,解决 var 问题, 新增 let, const)

var count = 100; //全局作用域

function foo1() {

var count = 0; //函数全局作用域

return count; //返回函数

}

if (count == 1) {

//块级作用域

console.log(count);

}

上面代码简单可以看出作用域分类,需要注意是,一个函数(function)也是块级作用域,简单来说,一般有 {}都可以算做是一个块级作用域.

作用域链

作用域里面嵌套作用域,就形成了作用域链. 外部作用域无法访问内部的作用域,看如下例子

function foo(){

var n=1

function foo2(){

var m=1

console.log(n) //1

}

foo2()

}

foo()

console.log(n) //err: n is not defined

上述代码中在全局中无法访问内部的n,但是在嵌套的内部foo2()可以访问外部的函数,这就是作用域产生的特殊效果.

明白了作用域链,我们再来看个例子(很有迷惑性,仔细看看哦):

var name = ‘Mike’; //第一次定义name

function showName() {

console.log(name); //输出 Mike 还是 Jay ?

}

function changeName() {

var name = ‘Jay’; //重新定义name

showName(); //调用showName()

}

changeName();

上面的例子你觉得输出的是什么呢?答案是Mike.在这里我们引出了一个新的概念,词法作用域作用域有两种模型:

词法作用域(静态):js查找是按照代码书写时候的位置来决定的,而不是按照调用时候位置

动态作用域:目前还有使用的有Perl,Bash (可以自行了解)

通过词法作用域的的规则我们可以再来分析一下

调用changeName()时,找到这个函数

定义var name = “Jay”

调用showName()

在changeName()里面查找是否有showName()这个方法,发现没有,向外层查找,找到了

调用console.log(name),在函数内部查找有没有name,没有,向外查找,找到了,name=“Mike”

输出Mike

闭包

了解了上面的知识之后,终于来到了闭包

闭包在两本书上的官方解释:

1.小"黄"书(你不知道的JavaScript): 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行.

2.红宝书(JavaScript高级程序设计): 闭包是指有权访问另一个 函数作用域中的变量的函数

非常抽象的一个概念,我自己的一个理解是:

当一个变量(就像上面的name)既不是该函数内部的局部变量,也不是该函数的参数,相对于作用域来说,就是一个自由变量(引用了外部变量),这样就会形成一个闭包.

怎么说呢?我们再来看看一开始我们使用的demo

let count = 500; //全局作用域

function foo1() {

let count = 0; //函数全局作用域

function foo2() {

let count2 = 1; //随便新增一个变量

// count++; 注释

debugger;

//console.log(count); 注释

//return count; 注释

}

return foo2; //返回函数

}

let result = foo1();

result(); //结果为1

result(); //结果为2

再次使用浏览器看看,这时我们就发现Closure已经消失了,这也就证实我说的,如果函数内部不调用外部的变量,就不会形成闭包.但是如果调用了外部变量,那么就会形成闭包. 这也就是说不是所有的函数嵌套函数都能形成闭包

最后我们再来看一个循环闭包的例子

for (var i = 1; i <= 5; i++) {

setTimeout(function timer() {

debugger;

console.log(i); // 输出什么?

}, 1000);

计算机网络

  • HTTP 缓存

  • 你知道 302 状态码是什么嘛?你平时浏览网页的过程中遇到过哪些 302 的场景?

  • HTTP 常用的请求方式,区别和用途?

  • HTTPS 是什么?具体流程

  • 三次握手和四次挥手

  • 你对 TCP 滑动窗口有了解嘛?

  • WebSocket与Ajax的区别

  • 了解 WebSocket 嘛?

  • HTTP 如何实现长连接?在什么时候会超时?

  • TCP 如何保证有效传输及拥塞控制原理。

  • TCP 协议怎么保证可靠的,UDP 为什么不可靠?

算法

  • 链表

  • 字符串

  • 数组问题

  • 二叉树

  • 排序算法

  • 二分查找

  • 动态规划

  • BFS

  • DFS

  • 回溯算法

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值