今天要总结的是作用域和内存问题。
1 基本类型和引用类型
- 动态的属性
基本类型就是上次讲的 5 种基本类型,就不赘述了。引用类型就是复杂类型,也就是object()。
和c++不同,引用类型的属性是动态的,也就是说可以动态的增加属性和方法,也
可以动态的删除属性和方法,如下:
var person = new object();
person.name = "xubing";
- 复制变量值
基本类型的复制没啥好说的,被复制的数据和复制后的数据分别占用不同的内存,修改一个另一个也不会变。主要是引用类型的复制。
var person1 = new object();
var person2 = person1;
上述代码中,person1 和 person2 是共享一片内存的,也就是说,如果通过 person1 改变对象的属性,person2 中该属性的值也会被改变。
- 函数传参
函数传参,传基本类型的参数相当于基本类型的复制,在函数中修改参数,实参的值不会被改变;传引用类型的参数,也相当于引用类型的复制,在函数中修改该参数,函数结束后引用类型的值会被改变。
- 检测类型
1 typeof 操作符可以确定一个变量是何种类型,包括 5 种基本类型和 1 种复杂类型,都可以确定。但是对于复杂类型来说,typeof 只可以确定变量是object,并不能知道它是什么类型的对象,所以又引入另一个操作符。
2 instanceof 操作符可以判断对象具体是什么类型的对象,用法如下:
alert(person instanceof object);
alert(clors instanceof Array);
如果类型和对象能匹配起来,就返回 true,否则返回 false(基本类型都返回false,因为基本类型不是对象)。
2 执行环境和作用域
- 执行环境、作用域链
每个函数都有自己的执行环境,当执行流进入函数时,函数的环境会被推入一个环境栈中,函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的作用是保证对执行环境有权访问的变量和函数的有序访问。
- 没有块级作用域
什么是块级作用域呢,看个下列例子就知道了。
for(int i = 0; i < 10; i++)
{}
上例中i所在的作用域就是块级作用域。在c++中,用花括号封闭起来的代码块都有自己的作用域。在js中,则不存在块级作用域,即,在块中定义变量,变量在离开块之后继续存在,并没有被销毁。
3 垃圾收集
js具有自动垃圾收集机制,也就是说,不需要手动释放内存。
js中常用的垃圾收集方式有两种,一种是 标记清除,另一种是 引用计数,其中,
标记清除是常用的方式。当两个对象通过各自属性的互相引用时,会出现
循环引用,引用计数就不能奏效,无法回收垃圾。
4 管理内存
为确保占用最少的内存就让页面获得更好的性能,在执行代码中只保存必要的数据。一旦有数据不用,就把它置为 null。