JavaScript中的变量、参数、作用域和作用域链

  • 基本类型和引用类型

    在JavaScript中有两种数据类型值。基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型值指的是可能由多个值构成的对象。在JavaScript中有5种基本数据类型,分别是:Undefined、Null、Boolean、Number、String(这个和其他编程语言不一样,需要注意)。基本数据类型是按值进行访问的,一般都存储在栈中。而引用类型的值都保存在内存堆上面,在内存栈上保存一个对它的引用(这个和C#,Java等编程语言存储对象的方式类似)。在JavaScript中提供基本的引用类型数据,它们是:Object、Array、Function等。这些具体会在后面的博文介绍。

    下面我们来看下基本数据类型和引用数据类型在一些关键点上的差异。先看基本数据类型。

    例如:var num1=5;var num2=num1。基本数据类型在内存中是这样的。如图:

    而作为引用类型我们可以使用下面代码来看下其内存布局。代码如下:

1 var obj1 = new Object();
2 var obj2 = obj1;
3 obj1.name = "Hello";
4 alert(obj2.name);   //输出Hello

    JavaScript中所有的函数参数都是值传递的。这对于基本数据类型很好理解,就是拷贝一份当前的值。函数内部使用的参数和外部传递的值互不影响。而作为引用类型的参数,这个值其实就是对象在堆内存上的引用。这个类似于上面介绍引用类型内存布局的部分。

  • 执行环境和作用域

    执行环境定义了变量或者函数有权访问的其他数据、决定了它们各自的行为。每一个环境变量都有一个与之关联的比变量对象。执行环境中定义的所有变量和函数都保存在这个变量中。

    全局执行环境是最外层的执行环境,一般在Web环境下指的是Window对象。所有全局变量和函数都是作为Window对象的属性和方法创建的。某一个执行环境的代码执行完毕以后,该环境被销毁(准确的说是从环境栈中弹出),保存在其中所有的变量和函数也都销毁了。全局执行环境需要等浏览器关闭才能退出。

    每一个函数都有自己的执行环境。当代码在一个环境中执行时,会创建变量对象的作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行环境的变量对象。作用域链中的下一个变量对象包含外部环境,再下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境。下面就通过一个例子来直观的看下这方面的内容。

    我们先来看这段简单的代码:

1 function a(x,y){
2     var b=x+y;
3     return b;
4 }

    在函数a创建的时候它的作用域链填入全局变量对象,该变量对象中包含全局变量和函数。如图所示:

    如果执行环境是函数,那么将其活动对象(activation object, AO)作为作用域链第一个对象,第二个对象是包含环境,下一个是包含环境的包含环境(这就是我们上面讲的作用域链)。还是看代码:

1 function a(x,y){
2     var b=x+y;
3     return b;
4 }
5 var tatal=a(5,10);

    这时候当执行到第5行代码,进入函数a进行执行时,作用域链如图:

  • 延长作用域链

    在JavaScript中执行环境的类型可以分成两种,全局和局部(函数)。但是有些语句在执行过程中可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除。具体来说就是当执行流进入try-catch中的catch块时和with语句时会临时添加一个变量对象。但这在构建大型应该时也会造成性能损耗。

  • JavaScript参数相关知识点

    JavaScript函数中的参数和其他编程语言也是不同的。JavaScript函数不介意你到底传递多少个参数,甚至实参和形参不对应也可以,因为在函数内部JavaScript使用一个arguments对象来保存外部传递的所有参数。arguments对象是一个类似于数组的对象,它可以提供arguments[0],[1]这样的方式来访问传递过来的参数。但是它不是数组,是一个对象。

1 function showArgs(arg1, arg2) {
2         var len1 = showArgs.length; //输出形参个数
3         var len2 = arguments.length;//输出实参个数
4         alert(len1);                //输出2
5         alert(len2);                //输出4
6 }
7 showArgs(1, 2, 3, 4);

    我们可以看到实参传递的所有参数都保存在arguments对象中,这个对象中根据下标会获取到一个个的实参。而函数对象的length只会获取该函数形参的个数。下面介绍argument的另一个重量级的属性callee。对于callee,它是一个指针,指向其函数(arguments对象所属的函数)。下面我们还是通过例子来了解这个属性。

 1 var sum = function sum(n) {
 2           var functionCode = arguments.callee.toString();
 3           //alert(functionCode);
 4           if (n <= 1) {
 5               return 1;
 6           }
 7           else {
 8               return n + arguments.callee(n - 1);
 9           }
10       };
11       alert(sum(100));    //输出5050

    这个例子是计算1+2+3+.....+99+100的。我们可以使用arguments.callee来进行递归调用。arguments.callee指向的是当前函数的指针。那一句注释掉的会输出sum函数的源代码。好了今天的博客就写到这边吧。后面还有关于对象和闭包的,会在后续的博客介绍。

时间: 2024-11-05 02:22:19

JavaScript中的变量、参数、作用域和作用域链的相关文章

一篇文章带你了解JavaScript中的变量,作用域和内存问题

作者 | Jeskson 来源 | 达达前端小酒馆 1 在JavaScript中的变量分别区分为两种: 一种为基本类型值,一种为引用类型值. 基本类型值指的是简单的数据段 引用类型值为可能由多个值组成的对象 引用类型的值是保存在内存中的对象,JavaScript不允许直接操作对象的内存空间,实际上操作对象的引用而不是实际对象. var dada = new Object(); undefined dada.name = "dada"; "dada" console.

JavaScript 中对变量和函数声明的提前示例

如题所示,看下面的示例(可以使用Chrome浏览器,然后F12/或者右键,审查元素.调出开发者工具,进入控制台console输入)(使用技巧: 控制台输入时Shift+Enter可以中途代码换行) var name = "xiaoming"; (function(){ var name = name || "小张"; console.info(name); })();// 小张 (function(){ name = name || "小张";

研究下JavaScript中的Rest参数和参数默认值

研究下JavaScript中的Rest参数和参数默认值 本文将讨论使 JavaScript 函数更有表现力的两个特性:Rest 参数和参数默认值. Rest 参数 通常,我们需要创建一个可变参数的函数,可变参数是指函数可以接受任意数量的参数.例如,String.prototype.concat 可以接受任何数量的字符串作为参数.使用 Rest 参数,ES6 为我们提供一种新的方式来创建可变参数的函数. 我们来实现一个示例函数 containsAll,用于检查一个字符串中是否包含某些子字符串.例如

JavaScript中的变量

JavaScript作为一种弱类型编程语言,其变量也是松散类型的.但是,这样松散的缺少拘束的变量规则,总会出现很多问题,而事实上,JavaScript中的变量,其实是包含两种数据类型的值:基本类型值和引用类型值,下面就对于这两种形式的变量值进行区分. 首先,要明确的一点是,变量只是一个容器,用来存放不同的值,所以说我们进行的所有操作,只是对存储在变量中的值的操作.先对这两种类型的值进行本质上的区分.第一.保存方式不同.基本类型的值只是一个单纯的字符串,它没有属性和方法(当然例如字符串的lengt

JavaScript中的变量在内存中的具体存储形式

栈内存和堆内存 JavaScript中的变量分为基本类型和引用类型 基本类型是保存在栈内存中的简单数据段,它们的值都有固定的大小,保存在栈空间,通过按值访问 引用类型是保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象,JavaScript不允许直接访问堆内存中的位置,因此操作对象时,实际操作对象的引用 结合代码与图来理解 let a1 = 0; // 栈内存let a2 = "this is string" // 栈内存let a3 = null;

javascript中的变量、作用域和内存问题

[变量][1]定义:可变的量,相当于给一个不定的数据起了一个外号.变量是存储信息的容器.[2]特性:js中的变量是松散类型的,可以保存任何类型的数据.它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变.[3]变量声明:变量可以在声明时赋值,但不能有其他操作,如+=.-=等 var a = 2;//是正确的 var a += 2;//是错误的 var a = 2++;//是错误的,++只能用于变量,不能

[转] javascript中的变量和垃圾回收

[From] http://www.imooc.com/article/4585 基本类型和引用类型 js中的变量虽然不区分类型,但是实际上Ecmascript包含两种类型,基本类型和引用类型. 基本类型有5种:Undefined,Null,Boolean,Number,String,基本类型是按值访问的,因为可以操作保存在变量中的实际的值. 引用类型的值是保存在内存中的对象.与其他语言不同,JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间.在操作对象时,实际

JavaScript 中对变量和函数声明的“提前(hoist)”的那些事儿

变量声明“被提前” JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对“先声明.后使用”的规则很熟悉,如果使用未经声明的变量或函数,在编译阶段就会报错.然而,JavaScript 却能够在变量和函数被声明之前使用它们.下面我们就深入了解一下其中的玄机. 先来看一段代码: (function() { //ReferenceError: noSuchVariable is not defined console.log(noS

(转)JavaScript 中对变量和函数声明的“提前(hoist)”

变量声明“被提前” JavaScript 的语法和 C .Java.C# 类似,统称为 C 类语法.有过 C 或 Java 编程经验的同学应该对“先声明.后使用”的规则很熟悉,如果使用未经声明的变量或函数,在编译阶段就会报错.然而,JavaScript 却能够在变量和函数被声明之前使用它们.下面我们就深入了解一下其中的玄机. 先来看一段代码: (function() { //ReferenceError: noSuchVariable is not defined console.log(noS