js高程第四章 变量、作用域和内存问题------学习笔记

高程第四章
基本数据类型(简单数据类型) :string,number,null,undefined,boolean
复杂数据类型 :object
基本类型的值和引用类型的值:
基本数据类型是 按值访问 的,因为可以操作保存在变量中的实际的值, 保存在栈内存中
引用类型的值是 按引用访问 的,因为引用类型的值是保存在内存中的对象,js不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,在操作对象时,实际操作的是对象的引用而不是实际的对象, 保存在堆内存中
1.动态的属性 :对于引用类型的值可以动态的添加属性和方法,也可以改变和删除其属性和方法
如果对象不被销毁或者这个属性不被删除,则这个属性将一直存在
2.复制变量值:基本类型的值的复制+引用类型的值的复制
(1)基本类型的值的复制:在变量对象上创建一个新值,然后把这个值复制到为新变量分配的位置上
(2)引用类型的值的复制 在变量对象上创建一个新值,然后把这个值复制到为新变量分配的位置上,但是这个值的副本是一个指针(指向存储在堆中的一个对象),复制操作结束后,两个变量实际上引用同一个对象,改变其中一个变量,就会改变另一个变量
3.传递参数:ECMAScript中所有函数的参数都是 按值传递
使用数值等基本类型值来说明按值传递参数容易,使用对象就不是很好理解了,但是 所有函数的参数都是按值传递的,对象也是按值传递的
ECMAScript中的函数参数都是局部变量
4.检测类型:
(1)typeof操作符:可以容易区分出string undefined number boolean typeof(null)=object(null是一个空对象)typeof(function)=function
chrome中 typeof(正则)-------function
ie,firefox typeof(正则)-------object
(2)instanceof操作符:因为所有的引用类型的值都是Object实例,所有在检测一个引用类型值和Object构造函数时,instanceof操作符始终会返回true
(3)instanceof内部原理:
var L=A.__proto__;
var R=B.prototype;
if(L===R)   return true;

执行环境及作用域
1.执行环境(环境)定义了变量和函数有权访问其他数据
2.每一个执行环境都有一个关联的 变量对象, 环境中定义的所有变量和函数都保存在这个对象里
3.全局执行环境是最外围的一个执行环境,全局执行对象被认为是window对象
4.执行环境中的所有代码执行完后,该环境被销毁,其中的所有变量和函数定义也随之销毁
5.全局执行环境知道应用程序退出(如关闭浏览器或者网页)才会被销毁
6.每个函数都有自己的执行环境,当执行流进入一个函数时,会把当前函数环境推入一个环境栈,而函数执行后,栈将其环境弹出,把控制权交给之前的执行环境
7.当代码在一个环境中执行时,会创建变量对象的一个作用域链,以保证对执行环境有权访问的所有变量和函数的有序访问
8.作用域链的前端始终是当前执行的代码所在环境的变量对象
如果是函数环境,将其活动对象作为变量对象,活动对象最开始只有一个变量arguments对象(全局环境不存在)
9.作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境,一直延续到全局执行环境,全局环境的变量对象始终都是作用域链的最后一个对象
10.标识符解析是沿着作用域链一级一级地搜索标识符的过程,始终从作用域链的前端开始,逐级回溯,直到找到标识符为止
11.一般一个函数的作用域链包含两个对象:它自己的变量对象(arguments对象)和全局环境的变量对象
12.内部环境可以通过作用域链访问所有外部环境,外部环境不能访问内部环境中的任何变量和函数,每个环境都可以向上搜索作用域链,以查询函数名和变量
13.每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链
1.延长作用域链
虽然执行环境只有两种:全局和局部(函数),但是可以通过在作用域前端临时增加一个变量对象,该变量对象会再代码执行后被移除
有两种语句可以加临时变量对象:
try-catch的catch块(创建一个新的变量对象)和with语句(将指定的对象添加到作用域链中)
2.没有块级作用域
js没有块级作用域
if:if语句的变量声明会被变量添加到当前的执行环境中,并不会随着 ‘ } ’ 结束被销毁
for:由for语句创建的i变量即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中
(1)声明变量
使用var声明变量会自动被添加到最近的执行环境中,如果初始化没有var声明,该变量会被添加到全局环境
(2)查询标识符
查询标识符从搜索开始,搜索从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符,如果局部环境找了,搜索停止;否则,沿着作用域链向上搜索,直到搜索到全局环境中的变量对象,如果还没有找到则意味变量没有声明
如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符,全局环境中的变量使用window.color访问全局color标识符

垃圾收集
js有自动的垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存,原理:找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间)周期性的执行这一操作
两种策略实现垃圾收集 : 1.标记清除+2.引用计数
1.标记清除
当变量进入环境(如在环境中声明一个变量)时,就将这个变量标记为“进入环境”,逻辑上来说,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们,当变量离开环境时,则将其标记为“ 离开环境
垃圾收集器会在运行时给存储在内存中的所有变量都加上标记,然后去掉环境中的变量以及被环境中的变量引用的变量的标记,而此后再被标记的变量就是要回收的变量
2.引用计数(不推荐,ie中访问非原生js对象时还存在问题)
引用计数是跟踪记录每个被引用的次数,当声明一个变量并将引用类型值赋给变量后,引用次数+1,如果引用的变量取得了另一个值,引用次数-1,当引用次数变成0时,则说明没有办法再访问这个值了,就可以将其占用的内存空间回收回来,在垃圾收集器下一次运行时释放引用次数为0的值所占用的内存
存在的问题 :循环引用----对象A包含一个指向对象B的指针,而对象B中也包含一个指向对象A的指针,如下例:
function problem(){
var objectA=new Object();
var objectB=new Object();
objectA.someOtherObject=objectB;
objectB.anotherObject=objectA;
}
objectA和objectB的引用次数永远不会是0,如果函数被大量多次调用,就会导致大量内存得不到回收
如何消除循环引用(循环引用也是导致内存泄漏的一种原因)
在不使用它们的时候手工断开连接;
objectA.someOtherObject=null;
objectB.anotherObject=null;
同时ie9将BOM和DOM对象转换成了真正的js对象(减少了js对象和DOM,BOM对象之间的循环引用)
3.性能问题
确定垃圾收集的时间间隔是一个非常重要的问题(动态触发)
如果垃圾收集例程回收的内存分配量低于15%,则变量、字面量和数组元素的临界值就会加倍;如果例程回收了85%的内存分配量,则将各种临界值重置回默认值
ie中window.CollectGarbage()方法会触发浏览器的垃圾收集功能,但是不推荐使用
4.管理内存
存在问题 :分配给web浏览器的可用内存数量通常比分配给桌面应用程序的少( 出于安全考虑 ),防止运行js的网页耗尽全部系统内存而导致系统崩溃,使内存受到限制,因此 确保用最少的内存可以让网页获得更好的性能
优化内存占用 :“ 解除引用 ”-------一旦有数据不使用,通过将其值设置为null来释放引用
解除引用并不意味着自动回收该值所占用的内存,而是让值脱离执行环境以便垃圾收集器下次运行时将其回收
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值