代码改变世界

由javascript 没有重载 引起的 内存分配问题学习

2015-04-23 17:48  coder_w  阅读(123)  评论(0编辑  收藏  举报

在ECMAScript中,函数名实际上是一个指向函数对象的指针(或者应该称作引用更合适),所以同一个函数可以有多个函数名(即多个指向同一内存块的引用 )。所以可以理解为什么没有 函数重载 。在对函数进行再声明的时候,事实上只是引用发生了改变。如下:

function test(num) {
     return num + 100;
}
function test(num){
     return num + 200;
}
var result = test(100);     // 300

看到这儿的时候,不由自主的问自己 在这里是指针发生了改变,还是变量值(即内存存储内容)发生了改变呢?
也就是说是
1. javascript 是 new 一块新的内存块 存储 第二个test 函数,然后将 test 指针指向这个新的内存块;
2.还是直接解引用,找到内存地址,将内存内容改变为第二个test函数呢?
结合上一篇文章中,javascript的 = 号是不会解引用的,而且function对象在new 的时候会 new 一个内存块,所以 是 第一种情况。
在查询重载相关的资料时,看到这样一篇文章
javascript arguments与javascript函数重载
文中提到arguments对象的内存分配问题,经查 Professional javascript for web developer 一书 及一些博文,得知,arguments对象的长度是 实参的个数,它和形参的内存存储空间是独立的,但是它们的值会同步。即当形参和实参想对应的时候,改变形参的值也会导致arguments对象内的实参改变。而在严格模式下,两者的值不会同步,且重写arguments的值会导致语法错误。

最近略微有点天马行空, - - 所以我们终于来到了正题: 内存分配问题。
一个程序占用的内存一般分为:
1. stack(栈) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2. heap (堆)一般由程序员分配释放, 若程序员不释放,则有GC处理,内存分配方式是链表。
3. static (全局区/静态区)
4. constant (字符常量区)
5. 程序代码区
这里主要讨论一下 stack、heap、constant(语言 JAVA)
stack: 基础类型的变量数据和对象的引用都在栈内存中分配,在程序退出作用域时,将为该作用域内的栈内存全都释放掉。
heap: 堆内存用来存放new出来的对象和数组,有GC进行动态的管理。且在stack中生成一个引用,引用在离开作用域后会被释放掉,但heap中占据的内存不会。
stack vs heap
堆的优势是可以动态分配内存大小,生存期也不必告诉编译器。缺点就是,存取速度慢,有可能导致内存碎片。
栈的优势是存取速度仅次于寄存器,数据可共享。缺点当然就是大小和生成期都必须是固定的。
constant:编译时就确认的并被保存在已编译的.class文件中的一些数据。包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用。
对于String,其引用是一定存储在栈中的,但是其值本身,会有两种情况:

          String a = "ss";
          String  b ="ss";
          System.out.println(a==b) // true
 这样编译器会认定a为字符串常量,存储在 常量池中。常量池也是共享的,所以声明b的时候会在栈中copy一个a的引用,但是a,b都是指向同一个内存空间。
          String a = new String("ss");
          String b = new String("ss");
          System.out.println(a==b) // false
 new生成的是不同对象,会存储在堆内存中,其引用也存储在栈中,但是两个引用指向不同的内存空间,因为堆是不共享的。
 但是当new a 对象的时候,会先去 constant 中寻找是否有 "ss" 字符串,如果有的话,则继续前面所说的。如果没有的话,就会先在constant中创建一个常量字符串"ss",再继续前面所说的堆里面的操作。
 扯到这里,感觉到已经有点越扯越远了,其实对java来说,将内存分配区域这样划分会有点粗糙,事实上的jvm运行的时候比这个复杂的多。例如:
 http://www.cnblogs.com/bolobeach/p/3388618.html
 但是本文不做深究,之后对JVM进行深入了解的时候再说。

引用:
http://en.wikibooks.org/wiki/Memory_Management/Stacks_and_Heaps
http://blog.itpub.net/8797129/viewspace-693648/
http://uule.iteye.com/blog/1417299
http://www.seas.upenn.edu/~ese112/spring09/programming/lectures/references.pdf