javascript的变量和C、java相去甚远,按照《画家与黑客》的说法,弱类型的变量是强大语言的基础;作用域与其他语言类似,但没有块级作用域;内存管理就要靠大学学的操作系统那门课的基础了;看来当时学的时候不知道有什么用,没准到哪天就豁然开朗了,所以知识储备还是必不可少的。
ECMAScript变量包括两种类型:基本类型和引用类型
基本类型是指简单的数据段(Undefined、Null、Boolean、Number、String),引用类型是指那些可能由多个值构成的对象(Object)。
这两种类型的区别是:基本类型操作的是保存在变量中的实际的值,在传递参数或复制变量的时候,直接把变量值传递给参数。而引用类型的值是保存在内存中的对象,传递参数或复制变量时传递的是指针。
String类型在其他语言中一般被当做对象,而在Javascript中是基本类型。
ECMAScript中传递参数的时候要注意引用的传递,实际上是把指针的内容传递给参数。参数指针变化时,不影响原引用。参数操作指向的内容时,原引用同步变化。
function setName(obj){ obj.name="JavaScript"; obj = new Object(); //参数的内容发生变化 obj.name="React"; } var person=new Object(); setName(person); console.log(person.name); //返回JavaScript/
实际上Java语言也是如此处理的:
public class JavaArguments{ public static void main(String[] args){ StringBuffer temp = new StringBuffer(); temp.append("hello"); test(temp); System.out.println(temp.toString()); //返回java } public static void test(StringBuffer sb){ sb.append(" java"); sb=new StringBuffer(); sb.append("new StringBuffer"); } }
变量类型的检测可以是用typeof操作符,但是对于引用类型,只能返回object字符串,如果想知道对象的类型,则需要instanceof操作符,正确则返回true,否则返回false。
console.log(person instanceof Object); console.log(person instanceof Array); console.log(person instanceof RegExp);
执行环境(execution context)是JavaScript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object)。
全局执行环境是最外围的一个执行环境。根据宿主环境不同,表示执行环境的对象也不一样。在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都作为window对象的属性和方法创建的。
某个执行环境中所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境知道应用程序退出--例如关闭网页或浏览器--时才被销毁)。
每一个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而在环境执行后,栈将其环境弹出,把控制权返还给之前的执行环境。
当代码在环境中执行时,会创建变量对象的一个作用域链(scope chain)。自身所在环境的变量对象是链条的前端,末端始终是全局环境的变量对象。如果一直找不到标识符,则会发生错误。
var color="blue"; function changeColor(){ var anotherColor = "red"; function swapColors(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; console.log("--------- 1-----------------") console.log(color); //red console.log(anotherColor); //blue console.log(tempColor); //red } swapColors(); console.log("--------- 2-----------------") console.log(color); //red console.log(anotherColor); //blue //console.log(tempColor); //undefined错误 } changeColor(); console.log("--------- 3-----------------") console.log(color); //red //console.log(anotherColor); //undefined错误 //console.log(tempColor); //undefined错误
with语句实际上就是指定了作用域链的前端。
JavaScript中没有块级作用域,所以for语句中声明的变量,在块的外部一样能够访问。
JavaScript具有自动垃圾回收机制
针对局部变量,局部变量只在函数执行的过程中存在,在栈(或堆)的顶部分配相应的空间,存储它们的值,函数执行结束后,变量也就没用了,此时即可释放内存。
判断变量是否有用的策略可能会因实现而异。
具体到浏览器,通常采用标记清除(mark-and-sweep)策略。
垃圾收集器在运行时会给存储在内存中的所有变量都加上标记,然后他会去掉环境中的变量以及被环境的变量引用的变量的标记。至此仍然有标记的变量将被视为准备删除的变量,因为环境中的变量已经无法访问到这些变量了。最后垃圾收集器完成内存清除工作。销毁那些带标志的值并回收他们所占用的内存空间。
作为开发人员,我们能够做的,是在全局变量和全局对象不再使用后,将其值设置位null来释放引用。这个做法叫做 解除引用(dereferencing)。
JavaScript变量可以用来保存两种类型的值:基本类型值(Undefined、Null、Boolean、Number和String)和引用类型值。特点如下:
关于执行环境:
关于内存管理: