本文共 2197 字,大约阅读时间需要 7 分钟。
1. 内存分配
1.1 基本类型值和引用类型值
ECMAScript变量包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值保存在栈内存中,而引用类型值保存在堆内存中。
5种基本类型Undefined、Null、Boolean、Number、String,它们的值在内存中分别占有固定大小的空间,因此可以把它们的值保存在栈内存中,也可以提高查询变量的速度,对于它们可以说是按值访问的。
如果是引用类型的值,则必须在堆内存中分配空间。因为它们的值大小不固定,因此不能保存在栈内存中,但内存地址的大小是固定的,所以可以将内存地址保存在栈内存中,再根据地址找到保存在堆中的值,这种查询方式叫做按引用访问。
1.2 动态属性
对于引用类型的值,可以为其添加属性和方法,也可以改变和删除其属性和方法,例如:
var myobj = new Object();myobj.name = "obj";alert(myobj.name);
但是不能给基本类型的值添加属性,例如:
var mystr = "string";mystr.name = "str";alert(mystr.name); //undefined
1.3 复制变量值
如果从一个变量向另一个变量复制基本类型的值,会在栈中创建一个新值,然后把该值复制到为新变量分配的位置上,例如:
var num1 = 5;var num2 = num1;
如果从一个变量向另一个变量复制引用类型的值,同样会将存储在栈中的值复制一份放到为新变量分配的空间中。但是这个值的副本实际是指向存储在堆中的一个对象的指针,例如:
var myobj1 = new Object();var myobj2 = myobj1;myobj1.name = "obj";alert(myobj2.name); //obj
1.4 传递参数
ECMAScript中所有函数参数都是按值传递的。在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量。
使用基本类型值传递参数比较简单,例如:
function add(num) { num += 10; return num;}var number = 20;var result = add(number);alert(number); //20alert(result); //30
如果使用引用类型值则稍复杂,例如:
function setName(obj) { obj.name = "obj";}var myobj = new Object();setName(myobj);alert(myobj.name); //obj
但这并不表明局部作用域中修改的对象会在全局作用域中反映出来,对象仍然是按值(内存地址)传递的,例如:
function setName(obj) { obj.name = "obj"; obj = new Object(); obj.name = "new obj";} var myobj = new Object(); setName(myobj); alert(myobj.name); //obj
1.5 检测类型
typeof操作符可以检测一个变量是哪种基本类型,但在检测引用类型时,总是返回object。通常我们并不是想知道某个值是对象,而是想知道它是什么类型的对象,可以使用instanceof操作符,语法如下:
result = variable instanceof constructor
如果变量是给定引用类型的实例,那么instanceof操作符就会返回true。根据规定,所有引用类型的值都是Object的实例。
2. 执行环境
2.1 环境与作用域
执行环境定义了变量或函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。这个对象无法访问,但解析器会在后台使用它。
全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。
当代码在一个环境中执行时,会创建由变量对象构成的一个作用域链,保证对执行环境有权访问的所有变量和函数的有序访问。全局执行环境是作用域链中的最后一环,标识符解析是沿着作用域链一级级搜索,从作用域链接前端(当前执行环境)开始,直到找到标识符为止。
2.2 作用域链的延长
有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除,即当执行流进入下列任何一个语句时,作用域链就会得到加长:
1) try-cache语句的catch块。
2) with语句。
2.3 块级作用域
JavaScript没有块级作用域,即花括号封闭的代码块中定义的变量可以在代码块外访问,例如:
if (true) { var color = "blue";}alert(color);
2.4 变量声明
在使用var关键字声明变量时,这个变量将被自动添加到距离最近的可用环境中。如果变量在未经声明的情况下被初始化,那么该变量会被自动添加到全局环境。
转载地址:http://fuqsa.baihongyu.com/