位置: 编程技术 - 正文

深入理解javascript作用域和闭包(深入理解新发展理念,推进供给侧结构性改革 心得体会)

编辑:rootadmin

推荐整理分享深入理解javascript作用域和闭包(深入理解新发展理念,推进供给侧结构性改革 心得体会),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:深入理解中国式现代化,深入理解中国式现代化,深入理解计算机系统,深入理解新发展理念,深入理解javascript,深入理解计算机系统,深入理解计算机系统,深入理解javascript,内容如对您有帮助,希望把文章链接给更多的朋友!

作用域

作用域是一个变量和函数的作用范围,javascript中函数内声明的所有变量在函数体内始终是可见的,在javascript中有全局作用域和局部作用域,但是没有块级作用域,局部变量的优先级高于全局变量,通过几个示例来了解下javascript中作用域的那些“潜规则”(这些也是在前端面试中经常问到的问题)。

1. 变量声明提前示例1:

此处的输出是undefined,并没有报错,这是因为在前面我们提到的函数内的声明在函数体内始终可见,上面的函数等效于:

注意,如果忘记var,那么变量就被声明为全局变量了。

2. 没有块级作用域

和其他我们常用的语言不同,在Javascript中没有块级作用域:

在javascript中变量的作用范围是函数级的,即在函数中所有的变量在整个函数中都有定义,这也带来了一些我们稍不注意就会碰到的“潜规则”:

在①处输出的值竟然是undefined,简直丧心病狂啊,我们已经定义了全局变量的值啊,这地方不应该为hello吗?其实,上面的代码等效于:

声明提前、全局变量优先级低于局部变量,根据这两条规则就不难理解为什么输出undefined了。

作用域链

在javascript中,每个函数都有自己的执行上下文环境,当代码在这个环境中执行时,会创建变量对象的作用域链,作用域链是一个对象列表或对象链,它保证了变量对象的有序访问。作用域链的前端是当前代码执行环境的变量对象,常被称之为“活跃对象”,变量的查找会从第一个链的对象开始,如果对象中包含变量属性,那么就停止查找,如果没有就会继续向上级作用域链查找,直到找到全局对象中:

作用域链的逐级查找,也会影响到程序的性能,变量作用域链越长对性能影响越大,这也是我们尽量避免使用全局变量的一个主要原因。

闭包

基础概念作用域是理解闭包的一个前提,闭包是指在当前作用域内总是能访问外部作用域中的变量。

深入理解javascript作用域和闭包(深入理解新发展理念,推进供给侧结构性改革 心得体会)

上面的示例在函数中返回了两个闭包,这两个闭包都维持着对外部作用域的引用,因此不管在哪调用总是能够访问外部函数中的变量。在一个函数内部定义的函数,会将外部函数的活跃对象添加到自己的作用域链中,因此上面实例中通过内部函数能够访问外部函数的属性,这也是javascript模拟私有变量的一种方式。

注意:由于闭包会额外的附带函数的作用域(内部匿名函数携带外部函数的作用域),因此,闭包会比其它函数多占用些内存空间,过度的使用可能会导致内存占用的增加。

闭包中的变量

在使用闭包时,由于作用域链机制的影响,闭包只能取得内部函数的最后一个值,这引起的一个副作用就是如果内部函数在一个循环中,那么变量的值始终为最后一个值。

上面的程序并没有按照我们预期的输入1-5的数字,而是5次全部输出了5。再来看一个示例:

调用createClosure()[0]()返回的是5,createClosure()[4]()返回值仍然是5。通过以上两个例子可以看出闭包在带有循环的内部函数使用时存在的问题:因为每个函数的作用域链中都保存着对外部函数(timeManage、createClosure)的活跃对象,因此,他们都引用着同一变量i,当外部函数返回时,此时的i值为5,所以内部的每个函数i的值也为5。那么如何解决这个问题呢?我们可以通过匿名包裹器(匿名自执行函数表达式)来强制返回预期的结果:

或者在闭包匿名函数中再返回一个匿名函数赋值:

无论是匿名包裹器还是通过嵌套匿名函数的方式,原理上都是由于函数是按值传递,因此会将变量i的值复制给实参num,在匿名函数的内部又创建了一个用于返回num的匿名函数,这样每个函数都有了一个num的副本,互不影响了。

闭包中的this

在闭包中使用this时要特别注意,稍微不慎可能会引起问题。通常我们理解this对象是运行时基于函数绑定的,全局函数中this对象就是window对象,而当函数作为对象中的一个方法调用时,this等于这个对象(TODO 关于this做一次整理)。由于匿名函数的作用域是全局性的,因此闭包的this通常指向全局对象window:

调用object.getScope()()返回值为global而不是我们预期的local,前面我们说过闭包中内部匿名函数会携带外部函数的作用域,那为什么没有取得外部函数的this呢?每个函数在被调用时,都会自动创建this和arguments,内部匿名函数在查找时,搜索到活跃对象中存在我们想要的变量,因此停止向外部函数中的查找,也就永远不可能直接访问外部函数中的变量了。总之,在闭包中函数作为某个对象的方法调用时,要特别注意,该方法内部匿名函数的this指向的是全局变量。

幸运的是我们可以很简单的解决这个问题,只需要把外部函数作用域的this存放到一个闭包能访问的变量里面即可:

内存与性能

由于闭包中包含与函数运行期上下文相同的作用域链引用,因此,会产生一定的负面作用,当函数中活跃对象和运行期上下文销毁时,由于必要仍存在对活跃对象的引用,导致活跃对象无法销毁,这意味着闭包比普通函数占用更多的内存空间,在IE浏览器下还可能会导致内存泄漏的问题,如下:

上面例子中匿名函数对外部对象target产生一个引用,只要是匿名函数存在,这个引用就不会消失,外部函数的target对象也不会被销毁,这就产生了一个循环引用。解决方案是通过创建target.name副本减少对外部变量的循环引用以及手动重置对象:

闭包中如果存在对外部变量的访问,无疑增加了标识符的查找路径,在一定的情况下,这也会造成性能方面的损失。解决此类问题的办法我们前面也曾提到过:尽量将外部变量存入到局部变量中,减少作用域链的查找长度。

总结:闭包不是javascript独有的特性,但是在javascript中有其独特的表现形式,使用闭包我们可以在javascript中定义一些私有变量,甚至模仿出块级作用域,但闭包在使用过程中,存在的问题我们也需要了解,这样才能避免不必要问题的出现。

再探JavaScript作用域 黄金守则第一条:js没有块级作用域(你可以自己闭包或其他方法实现),只有函数级作用域,函数外面的变量函数里面可以找到,函数里面的变量外面

Internet Explorer 浏览器介绍:别叫我IE 在上个星期,微软随Windows8.1正式推出了InternetExplorer的第一次预览版。这样,关于这款备受争议的web浏览器泄露版本的各种传闻也该休息了。我们现在

js类中获取外部函数名的方法与代码 比如我们要在一个类中设定一个方法可以根据调入一个方法保存在类变量中,等需要的时候可以通过访问类变量来得到。通常如果我们生成一个实例如

标签: 深入理解新发展理念,推进供给侧结构性改革 心得体会

本文链接地址:https://www.jiuchutong.com/biancheng/385664.html 转载请保留说明!

上一篇:js变量、作用域及内存详解(js变量作用域)

下一篇:js类中获取外部函数名的方法与代码(外部js获取当前vue实例)

  • 不动产销售额怎么填
  • 外币实收资本入账汇率
  • 金融服务担保费会计处理
  • 两家公司实际控制人为一个人
  • 其他现代服务税目包括哪些内容
  • 软件企业即征即退账务处理
  • 企业收取的租金会计分录
  • 作废的现金支票怎么处理
  • 年金终值的公式
  • 预付账款下月做什么科目
  • 房产过户的相关问题
  • 增值税普通发票怎么开
  • 出口退税可以用电子专用发票吗
  • 开专用发票的地址有错会有影响吗?
  • 一个月无纳税凭证怎么处理
  • 企业的主营业务收入
  • 诊所购药有差价怎么办
  • 电子税务局财报怎么报
  • 个人转让公司限售股纳税地点要求
  • 工程用的叉车计提折旧记到什么科目?
  • 汇兑产出的收益计入
  • 如何在excel中添加多行空白
  • 预付款挂账什么意思
  • 如何防止别人蹭热点
  • 免抵税额交地方教育附加吗
  • 超市收取进场费会计分录
  • 高温补贴需要缴纳社会保险费吗
  • php 缓存
  • 委托代销双方账务处理
  • vue手机端
  • antd:ConfigProvider+getPopupContainer解决筛选框遮挡问题(及其他浮层问题)
  • html/css/javascript
  • 外贸出口退税操作流程
  • 软件企业高新技术产品证明材料
  • 甲供材料总额法和差额法
  • 网络课平台用交税吗
  • 生产成本有什么
  • 先开发票后收款可以合并做账吗
  • 分页 php
  • 向境外机构支付的服务费税收政策
  • 以前年度亏损要调整吗
  • 记帐时借方是什么意思
  • 累计摊销咋算
  • sql server2008代理无法启动
  • 办公用品采购如何记账
  • 已使用的存货,计价方式不允许修改
  • 收到预付卡的发票是否可以报销呢?
  • 应交税费应交印花税贷方余额
  • 公司买东西算什么费用
  • 预提费用在新会计准则下该如何列支?
  • 如何调整以前年度的实收资本
  • mysql安装与配置详细教程
  • 如何远程连接小米摄像头
  • 设置密码保护的pdf怎么转word
  • win8系统手机
  • win2003和xp一样吗
  • ubuntu服务器安装matlab2014a环境配置
  • 怎么安装u盘里的文件
  • 如何显示文件后缀win10
  • mac如何全屏窗口
  • win7开机提示重启怎么办
  • windowsxp的功能介绍
  • mssvr.exe - mssvr是什么进程 什么用
  • linux 的ll
  • nodejs 代码加密
  • 基于web的学生成绩管理系统毕业论文
  • perl常用函数
  • javascript简单
  • 字符串转enum
  • jquery操作dom
  • html头像代码
  • ubuntu libtorch
  • 安卓状态栏宽度
  • [置顶] 转载自官方-unity5.0正式发布了,看看带来哪些重要的新特性!
  • js刷新当前窗口
  • javaScript parseInt字符转化为数字函数使用小结
  • jquery常用函数
  • 农商银行股权分红如何计算
  • 贵州网上税务大厅官网
  • 个体税务登记资料不齐怎么办
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设