变量类型:基本类型和引用类型
基本类型上节已经提到。基本类型的值是按值传递的,既改变形参的值不会影响实参
<html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> var x=1; function a(o){ o=100; alert(o); } a(x); alert(x); </script> </body> </html>
其中,a(x)为100 ,alert(x)为1 可见js的基本类型是按值传递的
引用类型:由多个值构成的对象,是按照共享传递的,也就是对象属性的形参的改变会影响对象属型的改变,对象形参的改变不会影响对象的改变。
<html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> var obj={x:1}; function a(){ arguments[0].x=2; } a(obj); alert(obj.x); </script> </body> </html>
可见alert(obj.x)为2 由此知对象属性的形参的改变会使对象的属性改变
<html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> var obj={x:1}; function a(){ arguments[0]=2; } a(obj); alert(obj.x); </script> </body> </html>
alert(obj.x)为1 可见对象的形参的改变不会影响对象
还有一点要注意的是,JavaScript有声明提前的特性,也就是说你可以先调用一个变量,然后声明,但是变量的赋值是不会提前的。
<html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> alert( a); var a=1; </script> </body> </html>
此时alert返回的结果是undefined ,可见a确实声明了
在变量的复制过程中,按值传递与按共享传递也是不同,对于按值传递 在string基本类型中,每一次对字符串的修改操作,实际都是新建了一个变量。
var a=1; var b=a;
其过程是a,b是完全独立的,这两个值参与的任何操作不会互相影响
按共享传递
var obj1={x:1}; var obj2=obj1; obj2.x=2; alert(obj1.x);
此时,alert输出的值也为2,可见属性的改变时会相互影响的,但对象之间互不影响。
instancof操作符 用于检查对象的类型,如Array,RegExp 用法实例:alert(colors instanceof Array); 其返回值为boolean
作用域
(执行)环境:js的最重要的概念。每个执行环境都有一个关联的变量对象,改环境中的变量和函数都保存在这个变量对象中,解释器在后台会使用它。
全局执行环境的变量对象是window,那么这个window对象就保存着全局变量和函数。
每一个函数都有一个执行环境,可以理解为局部环境,但执行流到达函数时,环境会置于一个环境栈中,当执行完毕后,环境栈会把这个函数环境弹出,继续执行下一个环境。
当一个环境遇到执行流时,会创建变量对象的一个作用域链,改作用域链的前端为当前的变量对象,如这个环境是函数,那么这个变量对象又称为活动对象,这个对象做开始只包含一个arguments变量。作用域链的下一个变量对象是包含环境,在下一个亦是上一个的包含环境,所以,作用域链的末尾的变量对象永远都是window(全局执行环境的变量对象),那么,内部环境可以通过作用域链访问外部环境,外部环境则不能。
也就是说,var声明的变量会被自动添加到离他最近的环境中(向上),在函数内部,就是该函数的环境,在with中,也是相应的环境。
那么,可以通过with或者try--catch来演唱作用域链,即在作用域链的前端增加一个变量对象。如下
function a(){ var a=true; with(location){ var url=href+a; } return url; } a();
需要注意一点,js没有块级作用域
变量查询(查询标识符)当某个环境为了读取或者引用一个标识符时,就要进行检索过程,搜索过程从作用域链的前端开始,向上逐级查询,遇到匹配的就停止。
垃圾收集:js具有自动清除垃圾的能力,切这个功能是循环进行的(时间间隔),垃圾清理主要是为了减少内存的浪费,对不再使用的变量进行销毁,释放内存。
1.标记清除法:js既然要自动清除垃圾,那么就要知道哪些是需要清理的,哪些是需要保留的,最简单的方法便是mark,当执行流执行到一个变量时,这个变量会被标记为“进入环境”,当执行结束后,便会被标记“离开环境”,当然标记的方法是多种多样的,可以是位翻转或者列表,这也是标记清除的思想。在标记清除中,垃圾收集器在运行时会对所有内存中的变量都加上标记,然后,他会去掉环境中的变量以及被环境中的变量引用的变量的标记,在此之后,在为这些变量添加标记,这些变量将被视为要删除的变量,最后完成内存清除操作。
2.引用计数:跟踪记录每个值得引用次数,每被变量引用一次,就加1,若变量去了其他的值,就-1,直到为0,进行清除。这回倒着一个循环引用问题的出现,导致内存的浪费。