资讯专栏INFORMATION COLUMN

《JavaScript高级程序设计》笔记:变量、作用域、内存问题

U2FsdGVkX1x / 2015人阅读

摘要:作用域链中的下一个变量对象来自包含外部环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境全局执行环境的变量对象始终都是作用域链中的最后一个对象标识符解析沿作用域链一级一级搜索标识符。

一、写在前面

最近研究了创建Android虚拟机、vscode结合weex开发Android APP、Vmware装MAC虚拟机的事,看的内容不够多,接下来加油

二、变量、作用域和内存问题 2.1 基本类型、引用类型

变量类型:

基本类型: 简单数据段,按值访问的,可操作变量中的实际值

引用类型:对象,按引用访问,操作对象的引用,能动态添加属性

变量复制:

基本类型:直接分配两个内存空间,互不影响

引用类型:复制了指针,指向堆中同一对象,相互影响

传参(见示例):

基本类型传值,互不影响

引用类型传地址,相互影响

// 示例
function setName(obj) {
    // 指向person,添加属性name
    obj.name = "Nicholas";
    // 指针指向新的内存空间
    obj = new Object();
    obj.name = "Greg";
    
    // 函数执行完毕后,局部对象立即销毁
}

var person = new Object();
setName(person);
alert(person.name);    //"Nicholas"

检测类型

typeOf特殊:null返回object

instanceof:引用类型检测,(某实例) instanceof (某类型)

2.2 执行环境、作用域

执行环境:定义变量或函数有权访问的其他数据范围,决定行为。中有变量对象,保存环境中定义的所有变量和函数,环境销毁,变量、函数销毁

全局执行环境,web中为window对象

局部执行环境,执行流进入函数,函数环境被推入环境栈,执行后,栈将其环境弹出,控制权返回之前的执行环境

作用域链: 在环境中执行代码,会创建变量对象的作用域链,保证(有权访问当前环境的)变量和对象有序访问

作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(activation
object)作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象

标识符解析:沿作用域链一级一级搜索标识符。从作用域链前端开始,逐级向后,直到找到标识符为止

内外关系:

内部环境可以通过作用域链访问所有外部环境,外部环境不能访问内部环境中的任何变量或函数

每个环境可以向上级搜素,但不能向下搜索进入另一个执行环境

2.3 延长作用域链

在作用域链前端加临时变量对象,执行后移除

try-catch中catch

with

function aaa( ) {
    var qs = "?id=12";
    // 引用location,with内部可用location的所有属性和方法
    with(location) {
        // href为locaiton.href
        var url = href + qs;
    }
   // 在aaa( )内可拿到with( )内定义的url
    return url;
}

catch特殊情况:IE8以前catch的错误对象会添加至执行环境的变量对象,catch外也能访问(IE9修复了)

2.4 没有块级作用域

{ } 封闭的代码块中定义的变量,执行后没有被销毁,依旧存在于{ }外部执行环境中

声明变量

var:自动添加到最接近的环境中。没有var直接声明,添加到全局环境中(严格模式下导致错误,不推荐)

查询标识符

从作用域链前端开始,向上逐级查询,直至匹配为止(先自身再向上)

访问局部变量比访问全局变量更快

2.5 垃圾收集

执行环境管理着代码执行过程中使用的内存
自动垃圾收集机制:实现所需内存分配、无用内存回收,自动管理。固定时间间隔,周期性检索不再继续使用的变量,打标记,释放其占用的内存

回收策略

标记清除(主流)

变量进入环境、离开环境,标记不同

标记方式:翻转某位,或以环境列表、离开环境列表区分,或其他

运行机制:内存中全部变量加标记,再去掉环境中的、被环境中引用的变量的标记,剩下还有标记的,准备删除,垃圾收集器清除内存,销毁值,回收空间

引用计数(不常见)

跟踪每个值被引用的次数

计数规则:引用类型的值赋给一个变量,引用次数加一;已经引用的变量不再引用它,引用次数减一

运行机制:垃圾收集器运行,释放引用次数为0的值所占的内存。

特殊情况:

循环引用(例:两对象间相互引用,则引用次数永不为0,无法销毁)

IE9之前,BOM、DOM对象以COM(使用引用计数策略)形式实现,循环引用后删除DOM,对应值也不会回收(通过赋值null,手动断开循环引用解决)。IE9后,BOM、DOM转为真正的js对象,避免了该问题

性能问题

IE7之前:内存分配量达到任一临界值(256变量、4096对象数组、64K字符串)则回收,缺点:如一直在临界值之上,则一直回收

IE7修正:临界值动态修正,初始与之前相等,回收的分配量低于15%,临界值加倍,回收的内存分配量85%,临界值恢复初始

手动触发方式(不推荐):

// 手动触发方式
// IE
window.CollectGarbage();
// Opear7~
window.opera.collect();

管理内存

内存分配:给web浏览器的少于给桌面应用的,防止系统崩溃

优化内存占用:只保存必要数据,不用的置null(解除引用,给全局中的用,局部的会自动销毁),等待下一次垃圾回收

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104964.html

相关文章

  • JavaScript高级程序设计》(第3版)读书笔记 第4章 变量作用内存问题

    摘要:具体说就是执行流进入下列任何一个语句时,作用域链就会得到加长语句的块。如果局部环境中存在着同名的标识符,就不会使用位于父环境中的标识符访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。 基本类型和引用类型的值 ECMAscript变量包含 基本类型值和引用类型值 基本类型值值的是基本数据类型:Undefined, Null, Boolean, Number, String ...

    lidashuang 评论0 收藏0
  • JavaScript高级程序设计笔记变量作用内存问题(四)

    摘要:局部变量只在函数执行过程中存在。此时,局部变量就没有存在的必要了,因此可以释放他们所占的内存以供他们使用。引用计数的含义是跟踪记录每个值被引用的次数。这一做法适合于大多数全局变量和局部变量的属性。 基本类型和引用类型的值 ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型的值指那些可能有多个值构成的对象。 动态的属性 ...

    Zack 评论0 收藏0
  • javascript高级程序设计笔记内存与执行环境

    摘要:因此,所有在方法中定义的变量都是放在栈内存中的当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用因为对象的创建成本通常较大,这个运行时数据区就是堆内存。 上一篇:《javascript高级程序设计》笔记:继承近几篇博客都会围绕着图中的知识点展开 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...

    fuyi501 评论0 收藏0
  • 学习笔记JavaScript 闭包是怎么通过作用链霸占更多内存的?

    摘要:闭包是怎么通过作用域链霸占更多内存的本文是作者学习高级程序设计第一小节的一点个人理解,详细教程请参考原教材。函数执行过程创建了一个函数的活动对象,作用域链的最前端指向这个对象。函数执行完毕返回值后执行环境作用域链和活动对象一并销毁。 JavaScript 闭包是怎么通过作用域链霸占更多内存的? 本文是作者学习《JavaScript 高级程序设计》7.2第一小节的一点个人理解,详细教程请...

    HmyBmny 评论0 收藏0
  • JavaScript高级程序设计》(第3版)读书笔记 第7章 函数表达式

    摘要:定义函数表达式的方式有两种函数声明。不过,这并不是匿名函数唯一的用途。可以使用命名函数表达式来达成相同的结果闭包匿名函数和闭包是两个概念,容易混淆。匿名函数的执行环境具有全局性,因此其对象通常指向通过改变函数的执行环境的情况除外。 定义函数表达式的方式有两种: 函数声明。它的重要特征就是 函数声明提升(function declaration hoisting) 即在执行代码之前会...

    邹立鹏 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<