变量、作用域和内存问题

变量、作用域和内存问题

1.JavaScript变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已。
(1)基本类型的值在内存中占据固定大小的空间,因此会保存在栈内存中;
(2)引用类型的值是对象,保存在堆内存中。
堆内存:随意存储,一般由程序员分配释放,或者程序结束时有OS回收。
栈内存:先进后出,有编译器自动分配释放,存放函数的参数值、局部变量的值等。

2.JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。操作对象时,实际上是在操作对象的引用而不是实际的对象。

3.复制
基本类型(undefined、null、boolean、number、string)复制,会创建这个值的一个副本,完全独立;
引用类型(对象)复制,复制的其实是指针,两个变量引用同一个对象。

var num1 = 57;
var num2 = num1;
num1 = 38;
console.log(num1, num2);    // 38 57

var obj1 = new Object();
var obj2 = obj1;
obj1.name = 'ligang';
console.log(obj2.name);     // "ligang" 

在这里插入图片描述
4. ECMAScript中所有函数的参数都是按值传递的。
(1)传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript的概念来说,就是arguments对象中的一个元素)
(2)传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部

// 示例--论证值传递:
function setName(obj) {
    obj.name = "ligang";
    obj = new Object();
    obj.name = "lg";
}
var person = new Object();
setName(person);
console.log(person.name);   // ligang 

如果是按引用传递,person会自动被修改为name为“lg”的新对象。
但是结果却是“ligang”,说明在函数内部修改了参数的值,但原始的引用仍然保持不变。
实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了,而这个局部对象会在函数执行完毕后立即被销毁。
在这里插入图片描述
5. 垃圾收集机制:标记清除和引用计数
当代码中存在循环引用现象时,“引用计数”算法就会导致问题。
解除引用(myObj = null;)是管理内存的好方式,切断变量与它此前引用的值之间的连接,让其脱离执行环境,以便垃圾收集器下次运行时将其回收。
6. 动态的属性
不能给基本类型添加属性

var str1 = new String("123");
str1.name = "string";
console.log(str1.name);     // "string"

var str2 = "456";
str2.name = "string";
console.log(str2.name);     // undefined 

引用类型和基本包装类型的主要区别就是对象的生命周期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着不能在运行时为基本类型值添加属性和方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值