Javascript学习笔记3——变量、作用域和内存问题

时间:2022-03-29 14:47:31


 

  Javascript变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在Javascript脚本的生命周期内改变,这可能是一个既有趣又强大,同时又特别容易出错的特性,但是Javascript变量实际的复杂程度还远不止于此。

  基本类型和引用类型的值

  Javascript中的变量和C#一样有值类型和引用类型之分。值类型的值直接保存在栈内存中,也就是说我们在操作值类型的变量时就是直接操作之内存中保存的值。而引用类型的值则保存在堆内存中,在栈内存(变量)中保存的其实是保存时机值的堆内存的地址。

  在Javascript中Undefined、null,String、Number、Boolean的值占用的内存大小都是固定的,都是值类型,而Object和Function都是引用类型。下图表示了值类型和引用类型的保存方式,如下图所示:

 Javascript学习笔记3——变量、作用域和内存问题  

       在Javascript中对象可以动态添加属性,但是基本类型不支持这样的操作。

1 var o = new Object();
2 o.Name = '小段';
3 o.Love = '小杰';
4 o.sayLove = function(){alert(this.Name+'爱上了'+this.Love)};
5
6
7 o.sayLove();

  上面的代码执行结果是 “小段爱上了小杰”。如果以上操作对应得是一个基本类型的值,那么执行上面的代码会报错"对象不支持“sayLove”属性或方法"。

  复制变量的值

  除了保存值的方式不同之外,在从一个变量向另一个变量复制值时引用类型和值类型也存在不同。如果从一个变量向另一个变量复制一个基本类型的值,会在内存中创建一个新值,然后将这个新的值保存到为新变量分配的位置上:

1       var num1= 11;
2
3       var num2 = num1;
4
5       num2=10;
6
7       alert(num1);  //11
8
9       alert(num2); //10

  当从一个变量向另一个变量复制引用类型的值时,也会将存储在栈中的值复制一份到为新变量分配的内存中。不同的是,这个值的副本实际上是一个指针,而指针指向的是保存在堆内存中的对象,复制结束后两个变量实际上引用的是同一的对象,因此改变其中一个变量的属性,就会影响另一个变量。如下面的例子所示:

var obj1 = new Object();
var obj2 = obj1;
obj2.name='小段';
alert(obj2.name); //小段



Javascript学习笔记3——变量、作用域和内存问题

  在Javascript的函数中无论是值类型还是引用类型都是按值传递的。只不过传递引用类型的变量时传递的是引用的副本,传递基本类型的变量时传递的是内存中的值的副本而已。

  我们可以使用typeof操作符来检测变量的类型,typeof操作符是确定一个变量是字符串、数值、布尔值、还是Undefined的最佳工具。如果变量的值是null或者是一个对象,则typeof操作符会返回一“object”;

  虽然在检测基本类型时typeof操作符是非常得力的助手,但是在检测引用类型的值时,这个操作符的用处不大。通常,我们不是想知道某一个变量是一个对象,而是想知道它是什么类型的对象。为此Javascript提供了instanceof操作符。其语法如此啊所示:

    result = variable instanceof constructor;

 太晚了明天再写吧

    公司突然要求我们连日加班,真是不幸啊。

 接着说说Javascript中变量的作用域吧。

  执行环境是Javascript中最重要的概念,执行环境定义和规定了变量或函数可以访问和的其他数据。决定了各自的行为。每个执行环境都有一个与之相关的变量对象,环境中定义的所有的变量和函数都保存在这个对象中。,虽然我们的代码中没有办法访问这个对象,但是解析器在处理数据时会在后台使用它。

  在web浏览器中全局执行环境被认为是Window对象,Javascript程序都在window对象中运行,当一个执行环境中的代码被执行完毕后,该执行环境的变量对象以及内部的所有变量和和函数定义将会被销毁。Window变量需要等到Javascript应用程序执行完毕后才会被销毁(关闭网页或浏览器)。

  当代码在一个环境中执行时,会创建变量对象构成的一个作用域链。作用域链的职责是保证保证对执行环境有权访问的所有变量和函数的有序访问。当前的执行环境位的变量对象总是位于作用域链的最末端。如果一个执行环境是函数,那么它的变量对象是其活动对象。