最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

JavaScript中关于变量作用域和内存问题的理解

来源:动视网 责编:小采 时间:2020-11-27 19:32:53
文档

JavaScript中关于变量作用域和内存问题的理解

JavaScript中关于变量作用域和内存问题的理解:变量作用域和内存问题1.基本类型和引用类型的值基本类型就是简单的数据段(5种值类型),而引用类型就是对象(操控对象的引用)。1.1复制变量值引用类型实际上在复制的时候,传递的是函数的指针,复制完成后,实际两个变量引用的都是同一个堆内存中的对象,改变这
推荐度:
导读JavaScript中关于变量作用域和内存问题的理解:变量作用域和内存问题1.基本类型和引用类型的值基本类型就是简单的数据段(5种值类型),而引用类型就是对象(操控对象的引用)。1.1复制变量值引用类型实际上在复制的时候,传递的是函数的指针,复制完成后,实际两个变量引用的都是同一个堆内存中的对象,改变这


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来解除引用

    相关文章:

    JavaScript变量作用域和内存问题(二)

    李炎恢Javascript视频教程

    文档

    JavaScript中关于变量作用域和内存问题的理解

    JavaScript中关于变量作用域和内存问题的理解:变量作用域和内存问题1.基本类型和引用类型的值基本类型就是简单的数据段(5种值类型),而引用类型就是对象(操控对象的引用)。1.1复制变量值引用类型实际上在复制的时候,传递的是函数的指针,复制完成后,实际两个变量引用的都是同一个堆内存中的对象,改变这
    推荐度:
    标签: js 了解 理解
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top