调试运行视频
python调试合集
java web 调试 视频合集
调试asp.net 项目相关合集
php 调试 视频合集
客服微信
客户问答
项目定制说明
作品发货方式
定制毕设需要的时间
成品可以修改吗
关于我们
翰文编程 CSDN博客
代做java毕业设计
信誉保证
购买流程
本站介绍
技术介绍
使用数据库
简单的基于地理图片的旅行路线还原
aScript 垃圾回收
Java中的不可变类
servlet 面试题
开发技术
ABO相关软件文件下载
基于Vue的生活废品回收系统的设计和实现
[免费获取]springboot 专升本志愿填报辅..
如何安装jdk
git 创建新项目,下载工程,合并和更新..
技术应用
ARM在adnroid开发应用
关于mysql
fusionCharts做bi展现基础技术
IoC容器类型
Ioc
移动手机软件的特点
J2ME介绍
手机软件现状
论文指导
广播电视大学论文应用指导要求
毕设题目参考二
毕设题目参考一
论文指导目录
开题报告指导
项目报告
论文开题报告格式
论文撰写的几大模块
当前位置:首页 > 查看
 

javascript作用域链

 来源:翰文编程 源码设计 定制服务  发布日期: 点击率:

第一种方式叫做命名函数方式,第二种叫做匿名函数方式,第三种是直接使用Function对象来定义函数,三种方式是等价的,并且都可以用一个变量保存该函数。其实前两种创建函数的方式是第三种的变种,由此可以看到所有函数都是Function对象的实例。

  函数的作用域功能是由函数内置的一个属性scope体现的,scope属性是一个类数组的集合,这个类数组的集合叫做函数的作用域链,作用域是函数的一个属性,作用域链其实就是该属性的数据类型。当我们创建一个函数时候,就是上面定义函数add01时候,函数的scope属性就会被同步创建,并且作用域链也会被构建,上面的例子里创建的函数都是属于全局的,因此作用域链只有一个元素即该类数组的length是1,类数组所包含的元素也是一个键值对类型,该元素包含所有全局变量例如:window,document,add01等等。

  上面的例子里add01是函数的标识符,当add01(1,2)加上了小括号的时候就是执行该函数了,执行一个函数时候,函数会创建一个运行期上下文,英文全称是:execution context,运行期上下文是函数的一个内部对象和作用域一样也是不能被外部访问的,每个运行期的函数都会有一个自己独有的运行上下文,当函数执行完毕后,该函数的运行上下文也会被销毁。当函数执行的时候,首先会初始化函数自带的scope属性,然后将函数自带的scope里的作用域链复制到运行期上下文里,运行期上下文里也包含一个作用域的属性,该属性也是用一个作用域链的类数组表示,复制出来的函数的作用域链会放到运行期上下文的作用域链里,这一步做好后,运行期上下文会初始化函数内部的局部变量和命名参数例如add01函数里的a,b,把这些变量存储到一个活动对象的变量里,初始化完成后这个活动对象也会加入到运行期上下文的作用域链里,这个活动对象会放到运行期上下文作用域链的最前端。其实在函数执行完毕销毁的对象就是这个活动对象,活动对象被销毁了对应的运行期上下文也就被销毁,但是原来存储在函数里的作用域还是保留的。

  作用域链的作用是对变量标识符进行解析,标识符就是变量的名字,例如add01、add02这些就是标识符,标识符的解析就是获取数据的位置或是如何存储数据。当函数执行时候,遇到每一个变量就会搜索运行期上下文的作用域链,这个过程都是从作用域链的头开始查找,也就是我上面说的从活动对象开始找起,如果找到与之对应的标识符,那么搜索过程便会停止,如果没有找到那么接着就会搜索作用域链的下一个对象,直到找到为止。不管是函数的作用域链还是运行期上下文的作用域链,链条的最后一个都是全局对象,其实全局对象是一个特殊的对象,如果我还是套用前面函数作用域的方式去理解全局对象,把一个网页当做一个最大的函数,这个函数对象就是window,网页的打开时这个window函数生命周期的开始,网页的关闭就是window函数的销毁,与window函数对应的还有一个全局的运行期上下文,那么用上面的理论理解全局变量应该就会简单多了。全局变量可以当做所有函数作用域的父作用域,当标识符解析到了全局变量时候,前面一定经过了n多个的作用域链中元素的遍历,因此到了遍历全局变量其实程序执行的效率是很低了,所以所有写高性能javascript代码的建议里都是要尽量减少全局变量的使用,如果非要使用全局变量也要在函数作用域内用一个局部变量替代全局变量,这是高性能javascript代码的一个基本要求,不过时下最新版的浏览器几乎都对这个特性进行了优化,访问全局变量不再像以前那么消耗性能了,不过ie的老版本的市场还是很大,而老版本的ie对全局访变量的访问那就是代码效率的毒瘤了。

  下面我要讲讲闭包和作用域的关系,有很多人把闭包等价于作用域或者是作用域链,这个有一定的道理,但是如果真的以为闭包就是等价于的这些的话,这个等价于就是错误的,闭包在javascript语言里是一个特殊的函数,闭包产生于函数执行的时候,也就是函数的名字加上了小括号使用的时候,这个时候就会创建闭包或者叫做定义闭包,这个过程和函数创建作用域的过程一样,而闭包的作用域链就是函数的运行期上下文,当执行闭包或者说使用闭包的时候,那么就会构建出闭包的运行期上下文,这个时候闭包也会构建一个活动对象,这个活动对象被置于它的作用域链的最前端,同时闭包还包含执行函数的活动对象,但这个活动变量是在闭包活动变量的后面,这样就会导致函数销毁时候内存无法及时回收,造成大量的内存资源的占用,因此使用闭包是个十分消耗计算资源的应用,前面我讲到要尽量把全局变量用局部变量替换,其实碰到跨作用域的变量引用,都要将其用局部变量替代,这样代码的效率和安全性会更好。

  还有很多童鞋认为this指针和作用域链没什么联系,这种理解是不正确的,其实this指针就是指向作用域链的上一级对象,但这种理解常常会误导某些人对this的理解,因为很多人在函数内部调用函数时候,发现被调用的函数this指针指向了全局变量,我们在实际开发里使用this指针最好是换个角度,this指针是调用某个函数上一级对象,例如obj.ftn(),那么ftn函数内部的this指针就是指向的obj,如果有个函数直接是ftn(),前面没有点,那么ftn函数里的内部指针就是window对象,this指针都是指向点号前面的对象,如果没有点号就是window对象,通过点号理解this指针比较方便,也不容易出错,但是通过作用域理解this为什么会有偏差了,原因就是全局作用域在作祟,在javascript里不管哪里直接调用函数,前面没有点的时候this都是指向全局的,我们不应该看这个方法是放到哪个函数里执行,其实this和作用域关系是紧密的,大家千万别怀疑这点。此外在作用域链的数组型的数据结构里,数组的每一个元素都含有一个this指针,this都是作为一个键值对预先定义好的,它的取值不由作用域链的创建所决定。因此有人认为this指针的使用其实也是跨域访问的观点也是不对,this指针的使用不存在跨域,它的效率也是非常高的。

请加微信,客服二维码请咨询购买,同时本程序源码配有系统运行视频 请联系客服索要视频文件


网址:毕设在线毕业设计网 http://www.bisheonline.net

服务范围:定制各类计算机程序设计,vue,jsp ,java 各类框架各类,开发工具 eclipse myeclipse idea vs 等,wap android ssm springboot asp.net php python (爬取,django,flask) vue node.js react ,winform uniapp小程序 等 E-mail:251836457@qq.com

友情链接: 翰文编程 CSDN博客   翰文编程 B站空间   计算机联盟  

翰文编程 源码设计 定制服务 版权所有

辽ICP备12012783


Copyright(C) 毕设在线(bisheonline.net) All Rights Reserved.


客服Q Q:251836457 翰文编程 源码设计 定制服务客服为你服务
360安全网址导航
Baidu