谈一谈js的内存分配

  因为js是一门动态语言,动态分配内存的方式让使用者运用快速便捷,却忽略了他的内存分配机制,今天我来试着理清思路。

  还是那个惯例,从基础讲起,然后发散思维,由浅入深。

  JavaScript有两种变量类型,原始值和引用值。原始值指的是原始数据类型,分别为undefined,null,number,string,boolean类型。引用值指的是复合数据类

型,即Object、Function、Array。

 原始值和引用值存储在内存的位置分别为栈和堆。原始值是存储在栈中的简单数据段,它们的值存储在变量访问的位置。引用值是存储在堆中的对象(存储在栈

中的只是一个指针,指向存储在堆中的实际对象)。

 基础都很简单,但是要活用,然后我们看一个闭包的例子:

for(var i=0,arr=[];i<=3;i++) {  
  arr.push(function(){  
    alert(i);  
  });  
}   
arr[0](); // 4  
arr[1](); // 4 

    关于这个经典闭包的例子,看了很多的解释,但我认为还是从内存的角度来解析最好,我们来活学活用。

(1)预解析,i,arr,匿名函数

(2)从上而下解析,i=0,arr[0]=匿名函数

(3)i=1,arr[1]=匿名函数

(4)i=2,arr[2]=匿名函数

(5)i=3,arr[3]=匿名函数

(6)i=4,循环结束

(7)执行arr[0],因为存入arr内的匿名函数其实是个指针,所以现在才开始执行匿名函数,此时i为4

(8)同理,arr[1]==arr[2]==arr[3]==4

其实在(1)时,i为undefind,而arr数组和匿名函数都是个指针,后续慢慢为arr数组开辟了内存空间,里面存入了匿名函数的指针



 

  既然你都知道了原理抓住了命门,那怎么解决是不是很简单了。

  所以解决闭包问题,我们有很多思路,可以让匿名函数即刻执行保存结果,也可以把当前循环时i的值保存在函数里等等。

  这里随便列几个供参考,思路可能还有很多

(1)

for(var i=0,arr=[];i<=3;i++) {  
    arr.push(function(i){  
        alert(i);  
    })(i);  
}  

这是让匿名函数即刻执行保存结果,注意这几个i的含义,传入参数i与变量i

 

(2)

for(var i=0,arr=[];i<=3;i++) {  
  let a = i;   
  arr.push(function(){  
    alert(a);  
  });  
}   

这是把当前循环时i的值保存,let是ES6新语法

posted @ 2017-08-19 16:27  ZpandaZ  阅读(423)  评论(0编辑  收藏  举报