摘要:变量作用域和内存问题基本类型和引用类型的值基本类型就是简单的数据段种值类型,而引用类型就是对象操控对象的引用。但是不但能访问自己的变量,也能访问和全局作用域下的变量。延长作用域链相当于创造了一个新的变量对象在当前作用域的上方。
变量作用域和内存问题 1.基本类型和引用类型的值
基本类型就是简单的数据段(5种值类型),而引用类型就是对象(操控对象的引用)。1.1复制变量值
引用类型实际上在复制的时候,传递的是函数的指针,复制完成后,实际两个变量引用的都是同一个堆内存中的对象,改变这个对象,两个变量的值也会同步改变。
1.2传递参数函数的参数都是按值传递的。其实我认为这种说法多少还是有些抽象。总结起来不如这样说。当传递给函数的变量是值类型时,那么传递给函数的这个原始变量的值不会随函数内部的影响而改变。当传递给函数的变量是引用类型(object)时,那么传递给函数的这个原始变量的引用不会随函数内部的影响而改变。其实这里不是太容易理解,比如举个例子来说明
var obj = { name: "andy" } function ChangeObj(val) { val.age = "25" val = { name:"zakas", age:40 } return val; } ChangeObj(obj); // {name:"zakas",age:40} console.log(obj) // {name:"andy",age:25}
上面这个例子中,函数中val的内存地址变了(引用变了),如果函数是按引用传递的话,那么val的引用就是obj的引用,val的应用变了,obj的引用也会跟随变化,所以obj的结果也应该是{name:"zakas",age:40}。而按值传递的话,obj赋值给val它的引用,但是他俩的引用是不关联在一起的,val引用的改变并不会影响obj的引用地址。
函数的形参就是函数作用域中的局部变量。当函数运行完是会被销毁的。
1.3检测类型instanceof 可以进行引用类型的更明确的检测。所以值类型在instanceof总全是false,值类型也没必要用其方法进行检测。instanceof只能区分Array Object 和 RegExp
2.执行环境每个执行环境都有一个变量对象,变量对象的概念很重要。它是作用域中所有定义的变量的一个大的集合;每个执行环境都有一个变量对象,存储着我们定义的所有变量,但是这个变量对象我们访问不到,但解析器处理数据时会在后台使用它。
function A() { var tempA; function B() { var tempB; function C() { var tempC } } }
B()的作用域链中包含3个对象,一个是自己的变量对象,还有A的变量对象和全局变量对象。A()中的作用域链包含2个对象,一个A()自己的变量对象,还有就是全局变量对象。因此A访问不了B的变量,只能访问自己的和全局的变量。但是B不但能访问自己的变量,也能访问A和全局作用域下的变量。
2.1延长作用域链with
With相当于创造了一个新的变量对象在当前作用域的上方。例如:
var obj = { name:"andy", sex:"man", hobby:"game" } function fn() { with(obj) { fnName = name; fnSex = sex; fnHobby = hobby; } console.log(fnName,fnSex,fnHobby) // andy,man,game } fn()
With方法会造成性能的严重损失,所以一般不建议用
2.2无块级作用域必须要知道这个概念,作用和区别,最老生常谈的一个问题:
for(var i =0 ; i < 10 ; i++ ) { setTimeout(function(){ console.log(i); },0) }
在理解这个问题的前提下,首先要知道定时器是异步的,即使是0,也要先放到缓存区中,当其他程序自上而下执行完毕之后再去调用。所以在其他程序自上而下执行完毕之后,由于没有块级作用域,i是全局的,已经变成10了,所以输出10个10。如果把i改为存在块级作用域的let,那么问题就迎刃而解了。
for(let i =0 ; i < 10 ; i++ ) { setTimeout(function(){ console.log(i); },0) }2.3垃圾收集
JavaScript具有自动垃圾收集机制
使用值的过程中,其实是相当于对变量分配的内存进行写入和读取的操作。JavaScript在创建变量的过程会分配内存,当变量不用时会自动释放掉,这个过程叫做垃圾回收机制,但是这个自动是混乱的根源,很多开发者因此觉得不用太关心内存问题,这是错误的。
原理:垃圾处理器会在默认情况下周期的进行检测,找出那些不用的变量,然后释放其内存。
回收策略:在局部环境中,函数调用完之后,垃圾收集器会跟踪哪个变量有用,哪个变量没有用,对于没用的变量,打上标记,以备回收其内存,但是标记的方法通常有另两个策略:
标记清除:从2012年起,所有浏览器全部使用标记清除的方法进行垃圾回收,并且所有对js垃圾回收的改进也是基于标记清除的方法进行算法优化。
引用计数:这个由于存在严重的循环引用问题,所以现在已经基本不用了。
因此,当写的程序占用较少的内存是高性能页面的一个很重要的点。所以当我们写程序时候,一旦数据不用了,最好设置成null来解除引用
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96546.html
摘要:执行环境的类型有两种全局全局执行环境局部函数执行环境每个环境都可以向上搜索作用域链,以查询变量和函数名但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。内部可通过作用域链访问外部,外部不能访问内部。 变量、作用域和内存问题 ECMAScript 数据类型 基本类型(5种): Undefined,Null,Boolean,Number,String typeof() 检测...
摘要:使用声明的变量会动被添加到最近的环境中查询标识符,现在作用域链的最前端开始搜索,逐步向上级查询,直到找到匹配的标识符,在变量查询中,访问局部变量要比全局变量更快,因为不需要向上搜索作用域。 基本类型和引用类型的值 基本类型值指的是简单的数据段;引用类型值指那些可能由多个值构成的对象。不能给基本类型添加属性,可以给引用类型值动态的添加属性。 基本类型按值访问,存放在栈内存中。引用类型按引...
摘要:在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。标记清除是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后再回收其内存 1.在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。 2.当从一个变量向另一个变量复制引用类型的值时,两个变量实际上将引用同一个对象,因此,改变其中一个变量,就会...
摘要:不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收 1 基本类型和引用类型的值 基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中 引用类型的值是保存在内存中的对象。JavaSc...
摘要:全局变量是最外围的一个执行环境,代码在环境中执行,会创建一个作用域链,用途是保证对执行环境有权访问所有变量和函数的有序访问。作用域链中最后一个对象始终是全局执行环境。内部环境可以通过作用域链访问所有的外部环境,外部则不能访问内部。 1、基本类型和引用类型的值 * 基本类型 : 指的是简单的数据段,五种基本类型是按值访问的,可以直接操作保存在变量中实际的值。 * 引用类型 : 指那些可能...
阅读 2177·2021-11-15 11:36
阅读 1323·2021-10-14 09:42
阅读 4133·2021-09-30 09:52
阅读 1672·2021-09-24 10:24
阅读 920·2021-09-02 09:56
阅读 2637·2019-08-30 13:11
阅读 3021·2019-08-30 13:06
阅读 908·2019-08-30 12:56