当前位置: 首页 > news >正文

马鞍山网站制作公司做网站含备案费么

马鞍山网站制作公司,做网站含备案费么,网站怎么做视频背景,vs2017网站开发时修改的页面未变化JS作用域链和闭包 引题作用域链词法作用域闭包思考题 闭包如何回收 引题 有没有人跟我一样,面试中要是问基础,最怕遇到的就是闭包问题,闭包在 JavaScript 中几乎无处不在,理解作用域链是理解闭包的基础,同时作用域链和…

JS作用域链和闭包

  • 引题
  • 作用域链
  • 词法作用域
  • 闭包
    • 思考题
  • 闭包如何回收

引题

有没有人跟我一样,面试中要是问基础,最怕遇到的就是闭包问题,闭包在 JavaScript 中几乎无处不在,理解作用域链是理解闭包的基础,同时作用域链和作用域还是所有编程语言的基础。

首先来看一段示例代码:

function bar() {console.log(myname)
}
function foo() {var myname = 'yy'bar()
}
var myname = 'qq'
foo()

如果用调用栈的方式来描述这个执行过程,可以参考下图:
在这里插入图片描述

如果你看过调用栈你的第一反应可能是按照调用栈的顺序来查找变量:
先查找栈顶是否存在 myname 变量,如果没有就往下查找 foo 函数中的变量,找到了所有返回 yy
但如果你运行这段代码就会知道,实际并非如此,最终输出结果其实是 qq,为何会是这种情况呢?要解释清楚这个问题,就需要先搞清楚作用域链。

作用域链

在每个执行上下文的变量环境中,都包含了一个外部引用,用来指向外部的执行上下文,我们把这个外部引用成为 outer
在这里插入图片描述

当一段代码使用一个变量时,JavaScript 引擎首先会在当前执行上下文查找该变量,如果找不到就会继续在 outer 所指向的执行上下文中查找。图中可以看出,函数 foobarouter 都指向全局执行上下文,所以 bar 函数中找不到变量 myname 时,下一步就是去全局执行上下文中找,结果为 qq。我们将这个查找的链条称为作用域链

不过还有一个疑问,bar 函数是在 foo 函数中被调用的,为何它的外部引用 outer 不是 foo函数执行上下文却是全局执行作用域呢?要回答这个问题,还需要知道词法作用域,因为在 JavaScript 执行过程中,其作用域链是由词法作用域决定的。

词法作用域

词法作用域是指作用域是由代码中函数声明的位置来决定的,所以词法作用域是静态作用域。结合图就能更好的理解这句话:

在这里插入图片描述

从图中可以看出,main 函数包含了 bar 函数,bar 函数中包含了 foo 函数,因为 JavaScript 作用域链是由词法作用域决定的,所以整个词法作用域链的顺序是:

foo 函数作用域——>bar 函数作用域——>main 函数作用域——>全局作用域

了解了词法作用域以及 JavaScript 的作用域链,再回过头来看上面的那个问题的答案就是:
因为根据词法作用域,foobar 函数在被声明时的位置决定了它们的上级作用域都是全局作用域,所以当 bar 函数使用了一个它自己没有定义的变量时,顺着它的作用域链往上找,就是全局作用域。

因此,词法作用域是代码编译阶段就决定好的,和函数是怎么调用的是没有关系的

闭包

了解了变量环境、词法环境和作用域链,接下来聊聊闭包可能你会更好的理解。先来看下面这段示例代码:

function foo() {var myname = 'yy'let test1 = 1const test2 = 2var innerbar = {getName: function() {console.log(test1)return myname},setName: function(newName) {myname = newName}}return innerbar
}
var bar = foo()
bar.setName('qq')
bar.getName()
console.log(bar.getName())

首先我们看当执行到 foo 函数内部 innerbar 这段代码时调用栈的情况,参考下图:

在这里插入图片描述

innerbar 是一个对象,包含了 getNamesetName 两个方法,这两个方法都是在 foo 函数内部定义的,并且这两个方法内部都使用了 mynametest1 两个变量。根据词法作用域的规则,内部函数 getNamesetName 总是可以访问它们的外部函数 foo 中的变量,所以当 innerbar 对象返回给全局变量 bar 时,虽然 foo 函数已经执行结束,但是 getNamesetName 函数依然可以使用 foo 函数中的变量 mynametest1,所以当 foo 函数执行完成之后,其整个调用栈的状态如下图所示:

在这里插入图片描述

从上图看出,foo 函数执行完后其执行上下文从栈顶弹出了,但是由于返回的 setNamegetName 方法中使用了 foo 函数内部的变量 mynametest1 ,所以这两个变量依旧保存在内存中。这就像是 setNamegetName 方法背的一个专属背包,无论在哪调用它们都会背着这个专属包,而且除了它们其他任何地方都无法访问这个专属背包,这个背包就被称为 foo 函数的闭包

现在我们对闭包一个正式的定义:

在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包。

那这些闭包是如何使用的呢?当执行 bar.setName('qq') 这个方法时,这段代码 JavaScript 引擎会沿着 当前执行上下文——>foo 函数闭包——>全局执行上下文 的顺序来查找 myname 变量,可以参考下图的调用栈状态图:

在这里插入图片描述
图中可以看出,setName 的执行上下文中没有 myname 变量,foo 函数闭包中包含了该变量,所以会修改闭包中的 myname 变量的值;同理,当调用 bar.getName 时,所访问的变量也是位于 foo 函数闭包中的。
所以执行的结果为:

// 1
// 1
// qq

Chrome的“开发者工具”中也可以看到闭包的情况

在这里插入图片描述

思考题

var bar = {myname: 'yy',printname: function() {console.log(myname)}
}
function foo() {let myname = 'qq'return bar.printname
}
let myname = 'out'
let _printname = foo()
_printname()
bar.printname()

执行 let _printname=foo() 这段代码的调用栈状态图可参考下图

在这里插入图片描述

_printname() 其实调用的就是 bar 对象的 printname 方法,而这个方法用到了 myname 变量,但是由于该函数作用域内并没有这个变量,根据词法作用域规则,它声明的位置决定了它的作用域链,它的上一个作用域就是全局作用域,它返回的 myname 变量就是全局作用域中的 myname,即输出结果为 out

通过开发者工具查看

在这里插入图片描述

如果你觉得 bar.printname() 应该返回的是 yy,在对象内部的方法中使用对象内部的属性是一个非常普遍的需求。但是 JavaScript 的作用域机制并不支持这一点,但是 JavaScript 的 this 机制 可以帮你理解并了解如何获取对象内部属性。

闭包如何回收

通常,如果引用闭包的函数是一个全局变量,那么闭包会一直存在直到页面关闭;但如果这个闭包以后不再使用的话,就会造成内存泄漏。

如果引用闭包的函数是一个局部变量,等函数销毁后,在下次 JavaScript 引擎执行垃圾回收时,判断闭包这块内容如果已经不再被使用了,那么就会回收这块内存。

所以,在使用闭包时,尽量注意一个原则:如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大,就尽量让它成为一个局部变量

http://www.yayakq.cn/news/142665/

相关文章:

  • 自适应网站建设优化建站河南郑州最新情况
  • 南京做信息登记公司网站大连做网站制作
  • 青岛网站建设官网百度网页安全警告怎么解除
  • 在哪几个网站里可以做淘客西安官网优化报价
  • 网站的布局有哪些wordpress 交流群
  • 石家庄规划太原seo关键词优化
  • 商务网站建设的一般流程是什么?购物网站建设信息
  • 怎么搭建网站设计策划网站
  • 两学一做微网站交流北京网页设计机构
  • 好发信息网网站建设php 网站 教程
  • ppt模板有哪些网站郑州市建设厅官方网站
  • 网站建设学生选课系统设计wordpress 小插件下载
  • 哪家可以做网站旅游电子商务网站建设背景
  • 建设银行官方网站首页入口中国商标查询官网
  • 七牛做网站网站建设和技术服务合同
  • 网站建设 美词php网站开发书籍
  • 开平市住房和城乡建设局网站湘潭专业网站建设湘潭振企专业
  • 网站建设标准天猫商城官网下载
  • 河南平顶山网站建设与管理专业网页设计自学网站
  • 江门网站关键词推广php怎么做p2p网站
  • 哪里有工程做的网站php进销存管理系统
  • c2c网站的建设网络营销公司搭建平台
  • 网站建设找盛誉网络做一个官网大概多少钱
  • 下载免费软件哪个网站好推广普通话喜迎二十手抄报
  • 做网站推广销售谷歌网站英文
  • 帝国cms企业网站东莞网页设计和网页制作
  • 网站图片比例纪念馆网站建设方案
  • 手机网站智能管理系统宁波建设银行网站首页
  • 定制开发 商城网站 最快郑州网络工程学院
  • 腾讯云服务器可以做传奇网站吗外贸营销网站建设介绍