Ch4 JS Variables, Scope, and Memory

时间:2021-09-02 16:24:21
1.基本类型与引用类型

 

   (1)JavaScript中的基本类型都是值类型,包括字符串类型也是值类型。

 

   (2)动态属性
   引用类型的值(对象)可以动态地添加、修改或删除属性和方法,但基本
类型的值却不可以,尽管不会报错。

 

      // 对象动态添加属性
      var person = new Object();
      person.name = "Nicholas";   // 动态添加属性 name
      alert(person.name);    // Nicholas

 

   (3)复制变量的值
   如果将一个变量 variable1 的值赋给另一个变量 variable2,如果两者
都是基本类型,则其中一个变量值的改变不会影响另一个。
   对于引用类型,变量之间的赋值(将一个变量名通过赋值运算符赋给另
一个变量名)实际上是对指向同一对象的地址引用(指针)的复制,所以,两
个变量尽管名称不同,却都是指向同一个对象的指针,通过这两个不同名称
的变量获取到的对象的值总是相等的,通过一个变量改变对象的值也同时也
会反映给另一个变量。如果变量 variable1 和 variable2 指向同一个对象
,当为变量 variable1 所赋的值不是另一个变量的名称,而是对象的值,
则可以直接改变变量 variable1 所指向对象的值,同时,变量 variable2
所指向的对象的值也将发生同样的改变。

 

   (4)参数传递
   所有函数的参数都是按值传递的,也就是把函数外部的值复制给函数
内部的参数。若向参数传递的是基本类型的值,被传递的值会被复制给
一个局部变量(即命名参数,或者说形参,再或者说是 arguments 对象中
的一个元素),这个局部变量的变化不会反映在函数外部;若向参数传递
的是引用类型的值,会把这个值在内存中的地址复制给一个局部变量,
这个局部变量的变化会反应在函数的外部。

 

      //-------------------------------------------------------
      //实参为值类型的例子:不会改变函数参数对应外部变量的值
      function addTen(num)
      {
         num += 10;
         return num;
      }

 

      var count = 20;
      var result = addTen(count);
      alert(count);    //20 - no change
      alert(result);   //30

 

      //--------------------------------------------------------
      // 实参为引用类型的例子:会改变函数参数对应外部变量的值
      function setName(obj)
      {
         obj.name = "Nicholas";
      }

 

      var person = new Object();
      setName(person);
      alert(person.name);   // Nicholas

 

      //---------------------------------------------------------
      // 实参为引用类型但仍按值传递的例子
      function setName(obj)
      {
         obj.name = "Nicholas";
         obj = new Object();
         obj.name = "Greg";
      }

 

      var person = new Object();
      setName(person);
      // 如果是按引用传递,则下面语句的结果将是 Greg
      // 但结果却是 Nicholas,所以证明是按值传递
      alert(person.name);   // Nicholas

 

   (5)类型判断
   要判断引用类型的对象具体属于哪种类型,可以使用 instanceof 运算
符,它最主要的用途是判断自定义对象的类型。其结果是一个 Boolean 类
型的值。 
   它的使用形式如下:

 

      result = variable instanceof constructor

 

   或者

 

      result = object instanceof class

 

2.执行环境和作用域

 

   (1)没有块级作用域
   JavaScript 中在局部代码块(函数内部的流程控制语句等,不包括函数
和对象代码块)内声明的变量可以在这个代码块的外部进行访问(仅限于直
接包含该代码块的函数或对象),而在像 C、C++、C#、Java这样的编程语
言中,块内变量是不能被外部访问的。
   JavaScript中,某些时候即使重新声明一个变量也不能消除这个变量
之前的值。如:

 

      function outputNumbers(count)
      {
         for (var i = 0; i < count; i++)
         {
            alert(i);
         }

 

         var i;  //variable redeclared
         alert(i);   //count
      }

 

   但如果将后声明的 i 进行初始化,则 i 的值将是后声明的值。

 

3.垃圾回收、性能和内存管理

 

   (1)避免循环引用
   像下面的代码会产生循环引用,在 IE8 及以下版本中会出现无法清除
已不再使用变量的情况。

 

      var element = document.getElementById(“some_element”);
      var myObject = new Object();
      myObject.element = element;
      element.someObject = myObject;

 

   (2)对于全局引用类型变量,全局引用变量的属性和发生循环应用的变
量,如果以后不会再被使用,就应该将 null 赋值给它,这样下次垃圾收
集器运行的时候就可以将其从内存中清除。