javascript基本类型和引用类型,作用域和内存问题
基本类型(null、undefined、boolean、number、string)和引用类型(Object 对象)
1 基本类型:只能不存一个值,一种类型;从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上,var num1 = 5;var num2 = num1;这样num1和num2 是完全独立的,操作互不影响。
2 引用类型:创建一个对象,可以添加、修改、删除属性和方法;当一个变量向另一个变量复制引用类型值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中,不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象,复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。var obj1 = new Object(); var obj2 = obj1; obj1.name = "summer";alert(obj2.name);//'输出 summer。
3 (函数)参数传递:基本类型的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样。在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量,而在向参数传递引用类型的值时,会把这个值在内存中放入地址复制给一个局部变量,因此这个局部变量的变化会反应在函数的外部。
实例A:
functionaddTen(){
num +=10;
return num;
}
var count = 20;
var result = addTen(count);
alert(cont);//20,没变化
alert(result);//30
由于传递的是基本类型值,所以传递后函数参数和外部变量相互独立,互不影响;
实例B:
function setName(obj){
obj.name = 'summer';
}
var person = new Object();
setName(person);
alert(person.name);// 'summer'
由于传递的是引用类型值,所以传递后函数参数和外部变量指向相同的内存地址,引用的是同一个对象;换句话说,即使这个变量是按值传递的,obj 也会按引用来访问同一个对象。于是,当在函数内部为obj 添加name 属性后,函数外部的person 也将有所反应,因为person 指向的对象在堆内存中只有一个,而且是全局对象。很多开发人员错误的认为:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的,可是请看下面的例子,
实例C:
function setName(){
obj.name = 'summer';
obj = new Object();
obj.name = 'winter';
}
var person = new Object();
setName(person);
alert(person.name);// 'summer'
这个和实例B 的区别是函数中为obj 重新定义了一个对象,以及重新设置 name属性的值。 如果person 是按引用传递的,那么person 就会自动被修改为指向其name属性值为"winter" 的新对象,但是原始的引用仍然保持不变。这说明,当在函数内部重写obj 时,这个变量引用的就是一个局部对象了,而这个局部对象会在函数执行完毕后立即被销毁。
4 检测类型:检测一个变量是不是基本数据类型,typeof 是最佳工具。检测引用类型的值时,用instanceof ,返回true 或false。如
alert(person instanceof Object);
alert(colors instanceof Array);
alert(patten instanceof RegExp);
5 作用域:所有变量(包括基本类型和引用类型)都存在于一个执行环境(也称为作用域)当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。:
执行环境有全局执行环境(也称为全局环境)和函数执行环境之分;
每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;
函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境;
全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
变量的执行环境有助于确定应该何时释放内存;
6 内存问题:javascript 是一门具有自动垃圾收集机制的编程语言,开发人员不必关心内存分配和回收问题。
离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除;
" 标记清除"是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后再回收其内存;
另一种垃圾收集算法是"引用计数",这种算法的思想是跟踪记录所有值被引用的次数。javascript引擎目前 都不再使用这种算法;但在IE 中访问非原生javascript 对象(如DOM元素)时,这种算法仍然可能会导致问题。
当代码中存在循环引用现象时,"引用计数"算法就会导致问题。
解除变量的引用不仅有助于消除引用现象,而且对垃圾收集也有好处。为了确保有效地回收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用。