位置: 编程技术 - 正文

深入理解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实例)

  • 企业所得税计算公式
  • 税收的本质是什么意思?
  • 企业开办费可不交税吗
  • 分支机构是否享受小微企业企业所得税优惠?
  • 小规模增值税征收条件
  • 费用的完成率怎么计算
  • 机构账户炒股是卖出后缴税么
  • 电子承兑汇票没开通能接受吗
  • 企业营改增后的会计处理有何变化
  • 外账的作用
  • 一般纳税人销售二手车增值税税率
  • 企业的福利费如何使用
  • 营改增账务处理实例
  • 研发样机转销售合法吗
  • 应收账款周转率怎么分析
  • 酒水专用发票税率
  • json去除某个字段
  • 失控发票的企业怎么处理
  • 如何安装纯净win10
  • 转回已核销的坏账
  • oss对象储存的副本储存原则
  • php错误级别有哪些
  • idea安装vue.js
  • yolov5怎么改进
  • php中的表达式简写是什么
  • 摇树的英文是什么
  • 前端上传文件夹怎么操作
  • 2023新版拳击航母
  • ls命令的作用
  • 在成本了核算工资怎么算
  • mongodb介绍
  • SQLite3 API 编程手册
  • 收购企业怎么做账
  • 增值税发票没有抵扣联能作废吗
  • 金税盘清卡失败增值税未申报或未比对
  • 进项的加计抵减怎么算
  • 营改增后企业所得税是国税还是地税
  • mysql出现箭头
  • 采用汇兑的方式归还前欠货款
  • 公司购买新车怎么入账
  • 监理公司成本核算方法
  • 企业做账的流程图
  • 会计一般什么时候忙
  • 会计账簿登记错误
  • 运动会活动奖品
  • 建筑业清包工合同范本
  • 收到货款会计录入
  • 公司收到现金货款怎么存银行
  • 没有按时对账
  • 收到支付宝认证怎么做账
  • 在建工程前期费用明细
  • 漏记以前年度财务费用怎么处理
  • 租房子租一半不租了违约金付的,房东不肯退钱怎么办
  • 同城票据交换差额户的帐号怎么查对方的帐号
  • 企业存货计价方法发生变更案例
  • 企业所得税必须预缴吗
  • 凭证账本是什么
  • mysql tmp_table_size和max_heap_table_size大小配置
  • 数据库聚簇索引和非聚簇索引
  • 不固定参数的存储器
  • mysql跨服务器查询语句
  • 大白菜u盘备份win10教程
  • windows微软官方
  • 在Linux系统中安装虚拟window
  • centos5.4
  • 金山卫士电脑版
  • win1021年更新
  • 列举javascript中的所有数据类型
  • android ndk cmake
  • CCProgressTimer 进度条动画在cocos2dx+lua中的使用
  • php上传文件到指定目录
  • python的删除
  • Android优化蓝牙
  • js分享软件集合
  • python import ssl
  • 长途客运手撕票能不能报销
  • 企业所得税减按90%计入收入总额
  • 国税系统打印不了发票怎么办
  • 环保税2018年开征文件
  • 山西税务体检医院
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设