JavaScript红皮书学习(4)--变量、作用域和内存问题

Posted by liveipool on December 19, 2016

变量、作用域和内存问题

按照ECMA-262的定义,Javascript的变量与其他语言的变量有很大的区别. Javascript的变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已. 由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期中改变.

4.1 基本类型和引用类型的值

  • ECMAScript变量可能包含两种不同类型的值:基本类型和引用类型值。
  • 基本类型值指简单的数据端,包括:Undefined、Null、Boolean、Number、String。
  • 引用类型值指那些可能由多个值构成的对象

在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。引用类型值是保存在内存中的对象。
当复制保存着某个对象的某个变量时,操作的是对象的引用。当在为对象添加属性时,操作的是实际的对象。

var person = new Object();
person.name = "lallana";  //此时操作的是实际的对象
alert(person.name);  //lallana
var o1 = {x : 1};
o2 = o1; //此时操作的是对象的引用
alert(o2.x);  //1

4.1.1 复制变量值

var num1 = 5;
var num2 = n1;

此后,这两个变量可以参与任何操作而不会互相影响。
4.1.11.png
4.1.12.png

4.1.2 传递参数

4.1.21.png

4.1.22.png

4.1.23.png
可以看出,person的引用没有变,也就是说在函数内部也无法改变person的引用,从这里可以看出,参数都是按值传递的。

4.2 执行环境和作用域

  • 执行环境是Javascript中最为重要的一个概念。有时也简称环境
  • 每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
  • 当代码在一个环境中执行时,会创建变量对象的一个作用域链。它保证对执行环境有权访问的所有变量和函数的有序访问。
  • 作用域链的前端始终都是当前执行的代码所在的环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。

4.21.png

4.22.png

4.23.png

4.24.png

4.2.1 延长作用域链

虽然执行环境的类型总共只有两种——全局和局部(函数),但还是有其他办法来延长作用域链。这么说是因为有些语句可以用在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除,这两种语句是:

  1. try-catch语句的catch块。
  2. with语句
    这两个语句都会在作用域链前端添加一个变量对象。with语句以后都不建议用了就不说了。catch语句是创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。

4.2.2 没有块级作用域

4.2.21.png

if语句和for语句都没有自己的执行环境。

4.2.22.png

函数有自己的执行环境。
在编写Javascript代码的过程中,不声明而直接初始化变量是一个常见的错误做法,因为这样可能导致意外。我们建议在初始化变量之前,一定要先声明,这样就可以避免这类问题。在严格模式下,初始化未经声明的变量就会导致错误。

4.2.23.png

4.2.24.png

4.3 垃圾收集

4.31.png

4.32.png

4.33.png

4.34.png

4.35.png

局部变量会在它们离开执行环境的时候自动解除引用,而全局变量会一直占用内存,因此尽量少使用全局变量,或在不用后手动清除。

4.4 小结

4.41.png

4.42.png

相关文章链接