变量、作用域和内存问题
基本类型和引用类型
JS包含两种不同数据类型的值,基本类型和引用类型。
基本类型是指简单的数据段:Undefined、Null、Boolean、Number、String,这几种基本数据类型是按值访问的,可以操作保存在变量中的实际的值
引用类型是指有多个值构成的对象:指保存在内存中的对象,JS不允许直接访问内存中的位置,所以实际是在操作对象的引用而不是实际的对象。
动态的属性
创建对象之后,可以动态的为其添加或删除属性和方法。
对于基本类型,则不可以添加属性。
复制变量值
除了保存方式不同,复制的时候,二者也有不同。
对于基本类型,复制的时候,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。二者相互独立。
对于引用类型,复制的时候,会将原变量的指针复制到新变量的位置上。改变一个就会影响到另一个。
var n1 = 5;
var n2 = n1; //n1 n2是两个相互独立的
var o1 = new Object();
var o2 = o1;
o1.name = "some";
alert(o2.name); //对o1的操作会影响o2
传递参数
JS的参数都是按值传递,也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。其原理和前述一致。
可以把JS函数的参数想象成局部变量
function setName(obj) {
obj.name = "aaa";
obj = new Object();
obj.name = "bbb";
}
var person = new Object();
setName(person);
alert(person.name);
//结果是aaa 函数内第一次对obj.name赋值修改了person对象,之后新建的obj对象在函数退出后就销毁了
检测类型
对于基本数据类型,使用typeof操作符可以确定一个变量是字符串、数值、布尔值、undefined,如果变量是一个对象或null,则返回都是object。
对于引用类型,使用instanceof操作符,可以确定是什么类型的对象,
语法:result = variable instanceof constructor
如果变量是给定引用类型的实例(通过原型链来识别),则instanceof会返回true。
alert(person instanceof Array);//如果person是Array数组对象,则返回true
执行环境和作用域
执行环境(简称 环境),定义了变量和函数有权访问的其他数据,决定了它们各自的行为,每个执行环境有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
全局执行环境是最外围的执行环境,根据JS实现所在的宿主环境不同,表示环境的对象也不一样。在web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。
某个执行环境中所有代码执行完毕之后,该环境就会被销毁,保存在其中的变量和函数定义也随之销毁。浏览器或网页关闭之后,全局环境就销毁了。
作用域的定义和C类似。
垃圾收集
JS具有自动收集垃圾的机制,执行环境会负责管理代码执行过程中的内存。其原理是垃圾收集器按照固定的时间间隔查找不再继续使用的变量,释放其内存。
标记清除
JS中最常用的垃圾收集方式是标记清除,当变量进入环境时,就标记为“进入环境”,当变量离开环境时,标记为“离开环境”。
引用计数
跟踪每个值被引用的次数,当声明一个变量并赋值一个引用类型值之后,次数即为1,如果同一个值又被赋给另一个变量,则次数+1,反之这个值引用的变量又取得了另外一个值,次数-1,当为0的时候,这个值就无法在被访问了,即可收回。
管理内存
确保占用最少的内存,可以让页面获得更好的性能。一旦数据不再有用,就将其设置为null来释放其引用——解除引用,这个方法适用于大多数全局变量和全局对象的属性。局部变量在退出时就会自动解除引用。