TBLEG
扫描微信账号

扫一扫微信二维码

js作用域链&内存回收&变量&闭包

2020-05-16 信息
区块链白皮书代写

闭包主要涉及到js几个其他特性:作用域链,垃圾(内存)回收机制,函数嵌套,等等

一、作用域链:函数在定义时候创建,用于寻找使用到变量 值一个索引,而他内部规则是,把函数自身本地变量放在最前面,把自身父级函数中变量放在其次,把再高一级函数中变量放在更后面,以此类推直至 全局对象为止.当函数中需要查询一个变量值时候,js解释器会去作用域链去查找,从最前面本地变量中先找,如果没有找到对应变量,则到下一级链 上找,一旦找到了变量,则不再继续.如果找到最后也没找到需要变量,则解释器返回undefined。

二、内存回收机制:一个函数在执行开始时候,会给其中定义变 量划分内存空间保存,以备后面语句所用,等到函数执行完毕返回了,这些变量就被认为是无用了.对应内存空间也就被回收了.下次再执行此函数时候, 所有变量又回到最初状态,重新赋值使用.但是如果这个函数内部又嵌套了另一个函数,而这个函数是有可能在外部被调用到.并且这个内部函数又使用了外 部函数某些变量话.这种内存回收机制就会出现问题.如果在外部函数返回后,又直接调用了内部函数,那么内部函数就无法读取到他所需要外部函数中变量 值了.所以js解释器在遇到函数定义时候,会自动把函数和他可能使用变量(包括本地变量和父级和祖先级函数变量(自由变量))一起保存起来.也就 是构建一个闭包,这些变量将不会被内存回收器所回收,只有当内部函数不可能被调用以后(例如被删除了,或者没有了指针),才会销毁这个闭包,而没有任何 一个闭包引用变量才会被下一次内存回收启动时所回收。

三、局部变量&全局变量

1、全局(global)变量作用域是全局,在Javascript中处处有定义;而函数内部声明变量是局部(local)变量,其作用域是局部性,只在函数体内部有定义,每次执行该函数时都会创建和破坏该变量。

2、全局变量作用域中使用变量可以不用var语句,但在声明局部变量是一定要使用var语句,否则会视为对全局变量引用。

3、

var scope = "local";声明变量在整个checkScope函数作用域内都有效,因此第一个document.write(scope);执行时scope引用是局部变量,而此时局部变量scope尚未定义,所以输出”undefined”。好编程习惯是将所有变量声明集中起来放在函数开头。document.write(window.scope)//输出global

全局变量总是存在于运行期上下文作用域链最末端,因此在标识符解析时候,查找全局变量是最慢。所以,在编写代码时候应尽量少使用全局变 量,尽可能使用局部变量。一个好经验法则是:如果一个跨作用域对象被引用了一次以上,则先把它存储到局部变量里再使用(document、 window等)。

在执行JavaScript代码过程中,当遇到一个标识符,就会根据标识符名称,在执行上下文(Execution Context)作用域链中进行搜索。从作用域链第一个对象(该函数Activation Object对象)开始,如果没有找到,就搜索作用域链中下一个对象,如此往复,直到找到了标识符定义。如果在搜索完作用域中最后一个对象,也就是 全局对象(Global Object)以后也没有找到,则会抛出一个错误,提示用户该变量未定义(undefined)。这是在ECMA-262标准中描述函数执行模型和标识 符解析(Identifier Resolution)过程。

由ECMA-262标准第三版定义,该内部属性包含了函数被创建作用域中对象集合,这个集合被称为函数作用域链,它决定了哪些数据能被函数访问。作用域第一个对象始终是当前执行代码所在环境变量对象

function a(x,y){

var b=x+y;

return b;

}

在函数a创建时候它作用域链填入全局对象,全局对象中有所有全局变量

var tatal=a(5,10);

执行此函数时会创建一个称为“运行期上下文(execution context)”内部对象,运行期上下文定义了函数执行时环境。值按照它们出现在函数中顺序被复制到运行期上下文作用域链中。它们共同组成了一 个新对象,叫“活动对象(activation object)”,该对象包含了函数所有局部变量、命名参数、参数集合以及this,然后此对象会被推入作用域链前端,当运行期上下文被销毁,活动对 象也随之销毁。

ECMAScript变量可能包含两种不同数据类型值:基本类型值和引用类型值。基本类型值指是那些保存在栈内存中简单数据段,即这种值 完全 保存在内存中一个位置。而引用类型值是指那些保存堆内存中对象,意思是变量中保存实际上只是一个指针,这个指针指向内存中另一个位置,该位置保存 对象。

5种基本数据类型:Undefined、Null、Boolean、 Number和String。这5种基本数据类型值在内存中分别占有固定大小空间,因此可以把它们值保存在栈内存。

如果赋给变量是一个引用类型值,则必须在堆内存中为这个值分配空间。由于这种值大小不固定,因此不能把它们保存到栈内存中。但内存地址 大小 是固定,因此可以将内存地址保存在栈内存中。这样,当查询引用类型变量时,就可以首先从栈中读取内存地址,然后再“顺藤摸瓜”地找到保存在堆中值。

保存在栈内存中每个值,分别占据着固定大小空间,可以按照顺序来访问它们。如果栈内存中保存是一块内存地址,则这个值就像是一个指向对象在堆内存中位置指针。保存在堆内存中数据不是按顺序访问,因为每

全文阅读
文章关键词
函数
javascript
js
数据类型
scope
扫描关注微信账号

试试长按二维码加关注