涉及到的知识与内容
作用域,引擎,编译器,闭包
作用域的初步概述
作用域对于我们来说是一个比较重要的知识点,今天主要来讲解一个我所理解的作用域,本篇文章可能会带你了解不一样的作用域知识
1作用域概述
在javascript中我们正常学习中出问题的就是作用域问题,它其实并不是我们所理解的那么难,如果你学习过java或者是C#等语言你就能知道作用域对于一个程序而言,作用是有多大
作用域,简单的理解就是我们变量在某一个区域内的生效
这么说还是有点抽象的
我们进行一下简单的了解一下关于引擎,作用域,编译器这三个哥们之间的关系
引擎,作用域,编译器
通常我们所说的引擎是浏览器中解析代码的东西,比如我们经常开发使用的谷歌,它的v8内核解析速度真是惊人的快
我们要记住一点,要记住他们的执行顺序偶~~~~
我来讲解一下把
每一个角色都会给他们分配工作
1 引擎: 他会从上而下负责javascript程序的执行
2 编译器: 他负责的时语法分析,和程序执行的操作
3 作用域:负责收集程序的维护和收集,它有自己的作用域
第一:编译器会首先执行,他会在程序里进行解析,做的是语法分析,生成代码给js引擎执行的脏活和累活
看到这样的语句 var a =10;
js编译器看到var a 这样的语句时
会拍一拍作用域,到里面去寻找是否存在a 这个变量名,如果有的话,编译器就
会往下继续编译,如果没有的话,就会在作用域中生成一个新的变量声明
然后会为引擎生成相应可以运行的代码
引擎得到了这个代码以后,会到这个作用域里进行查找,是否有这个变量,它所要做的工作就是要找到a这个变量,然后给他进行赋值 a =10的操作,如果它发现有的话,它就会直接进行赋值,如果没有的话他会抛出一个异常,提示我找不到这个变量
这样听来是不是就好理解了
正题
第一作用域问题分为局部作用域和全局作用域,也就是我们所说的GO 和 AO,GO 在一开始就生成了一个全局对象,全局对象中存储全局内的变量,AO是在函数被调用的时候生成的存放函数内的变量,函数内的var在函数内是一个块级作用域的,在函数被定义时会进行预解析,解析顺序是,变量声明提升然后是函数声明提升,只是声明提升不会进行变量提升,顺序 - 预解析全局,遇到函数的定义,预解析函数
作用域链 的一个解读 :
GO 和 AO的概念
当函数被定义的时候函数会生成一个【【scope】】属性,这个是js引擎中的
一个隐式属性这个属性会保存函数的作用域链上,每一个函数作用域中都有一
个GO,这个作用链我的理解是一个压栈操作,GO内存储的是全局对象,当函数
被调用的时候会在作用域內生成一个属于自己的AO,这个AO中存储的是自己
函数内部的对象,当函数执行完后,垃圾回收机制把函数回收,也就是AO销毁掉,
但是作用域中还是会存在GO对象,并且AO对象会在GO对象的前面
也就是说 函数为定义前是 0 GO ,函数被调用是,作用域链就变成了 0 函数名 -AO 1 GO
还有一种就是闭包 ,我的理解就是数据的劫持,在一个函数中嵌套另外一个函数,通过这个函数对外部的函数里的内容进行修改,
这个其实就是作用域链 和 垃圾回收机制的结合
作用链中外部的函数执行完后 内部的函数进行定义,这个函数在作用域中会有
前面函数的内容,也就是说
它现在没有自己的AO,只有他人的AO 和 全局的GO,
比如有一个函数名字叫做A
A函数中定义了一个函数B
A执行
A : 0 A-AO 1 GO
A执行完后B执行
B没有自己的AO,但是他现在有了A函数的AO,和全局的GO
B : A-AO GO
当函数执行时有了自己的AO
就变成了
B: B-AO A-AO GO
B函数执行完就会销毁B的AO
然后A在销毁自己的AO
闭包就是不想让A的AO执行完毕
我们可以进行这样的操作
将B的函数直接return 出去
因为现在B函数有A的AO 和 GO
就算A现在执行完毕,B会紧紧的抓住A的AO不会松手
A执行完毕后A的AO也不会销毁,一直储存在B的作用域链中
闭包可能会造成内存消漏 和 加载过慢的问题存在,不建议使用过多的闭包