第四章 变量类型、作用域和内存问题

1、基本类型和引用类型

1.1 基本类型

定义

JS的基本类型包括:Undefined, Null, Boolean, Number和String。

复制变量值

基本类型的值从num1复制到num2上时,会在num1对象上复制一个新值,然后把该值复制到为num2分配的位置上。相当于给num2开辟了新的内存空间。

var num1 = 5;
var num2 = num1;
BasicCopy.png
传递参数

ECMAScript中所有函数的参数都是按值传递的。在向函数传递基本类型的值时,被传递的值会被复制给一个局部变量。

function addTen (num) {
    num += 10;
    return num;
}
var count = 20;
var result = addTen(count);
alert(count);  //20,没有变化
alert(result);  //30

传递Number类型的变量,在函数内部修改num,不会影响外部的count。

1.2 引用类型

定义

引用类型如对象。对于引用类型的值,可以为其添加动态属性和方法。

var person new Object();
person.name = "Nicholas";
复制变量值

引用类型的值从obj1复制到obj2时,会创建一个指针副本。并将该指针指向存在堆内存中的对象。

var obj1 = new Object();
var obj2 = obj1;
obj1.name="Nicholas";
alert(obj2.name); //"Nicholas";
RefCopy.png
传递参数

在向函数传递引用类型的值时,传递的是对象的引用。换句话说,即使这个变量是按值传递的,参数也会按照引用来访问同一个对象。

function setName (obj) {
    obj.name = "Nicholas";
}
var person = new Object ();
setName(perspn);
alert person.name(); // Nicholas

因此在函数内部修改obj对象,也会影响到外面的person对象。
注意,若在函数内部new Object,仍是一个局部对象,在函数执行完毕后会被立即销毁。

检测类型
//typeof 检测变量类型
var num = 12;
var obj = new Object ();
alert( typeof num); //number;
alert( typeof obj); //Object; 

//instanceof 检测对象是什么类型,如果是则返回true。
var obj = new Object();
alert(obj instanceof Array); //变量对象obj是Array类型吗?
alert(obj instanceof RegExp);//变量对象obj是RegExp类型吗?

2. 执行环境及作用域

执行环境

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
web浏览器的全局执行环境是window对象,所有的全局变量和函数都是基于它创建的。对于函数都,它们有自己的执行环境。

作用域

个人认为执行环境即为作用域。当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域的前端,始终是当前执行的代码所在环境的变量对象。

var color = "blue";
function changeColor () {
    var anotherColor = "red";
    function swapColor () {
        var tempColor = anotherColor;
        anotherColor = color;
        color = tempColor;
     // 这里可以访问color, anotherColor, tempColor
    }
    //这里可以访问color, anotherColor,但不能访问tempColor
    swapColor();
}
//这里只能访问color
changColor();

下图展示了上述代码的作用域链:


作用域.png

在作用域链中,内部环境可以通过作用域链访问所有外部环境。外部环境不能访问内部环境中的所有变量和环境。
当在某个环境中为了读取或写入而引用一个标识符时,会从作用域链的前段开始搜索,向上逐级查询,若匹配到该变量名,则停止搜索。否则一直会搜索到全局对象,若全局环境也未找到,则意味着该变量尚未声明。

延长作用域链

当进入下列语句时,作用域链就会得到加长。

  • try-catch语句中的catch块
  • with语句
没有块级作用域
//例如,for循环语句里定义的变量在for循环结束后仍然存在于其外部的执行环境。
for( var i=0; i <10; i++){
    dosomething(i);
}
alert(i) //10;  

如果初始化变量时没有使用var声明,该变量会自动被添加到全局变量。

3. 垃圾收集

JavaScript具有自动垃圾收集机制,具体到浏览器中的实现有两种策略:

  • 标记清除
  • 引用计数

对于开发人员,不必过分关注内存管理问题。若要优化页面性能,可为不再有用的数据释放其引用,即

var globalPerson = new Object();
globalPerson.name = "Nicholas";
//手工解除globalPerson的引用
globalPerson = null;

你可能感兴趣的:(第四章 变量类型、作用域和内存问题)