JavaScript 变量的作用域

一、 基本类型和引用类型

   基本类型值指的是简单的数据段,而引用类型值指的是那个可能由多个值组成的对象  
   将一个值赋值给变量时,javascript解析器首先要确定是基本类型还是引用类型,基本数据类型可以直接操作保存在变量中的值,而引用数据类型的值是保存在内存中的对象,在操作对象时,实际上操作的是对象的引用而不是实际的对象

二、 变量的赋值

  1、 如果从一个变量上向另一个变量上复制__基本数据类型__的值,会在变量对象上创建一个新值,然后把该值复制到新变量的位置上,这个很好理解,来看下例子:

    var num1 = 5;
    var num2 = num1;

  

  上面代码赋值的过程,如下图:

2、这是基本数据类型,而引用类型呢?其实同样会将原来变量上的值复制一份到新的变量当中,只不过,复制的其实是原来变量的一个指针,而这个指针指向存储在堆中的一个对象。复制完成后,两个变量都指向了堆中的同一个对象,所以改变其中一个的值,会对另外一个产生影响。有以下代码

    var obj1 = new Object();
    var obj2 = obj1;
    obj1.name = "Nicholas";
    alert(obj2.name);  //"Nicholas"

  

    那么上面这段代码执行的过程如下图:

三、 传递参数

   在javascript里面,参数的传递都是按照值类型来传递的,即使你传入的是一个引用类型

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

  

  上面代码的返回结果貌似参数是引用类型的传递,因为开始person对象没有属性,调用了setName方法之后,给参数obj加上了name参数,然后外面的person打印person.name竟然是有值的,这是很明显的引用传递的效果。但是不要被这种现象所迷惑,javascript在传递引用类型的参数的时候,只要这个参数不发生改变,那么还是按照引用类型来处理,但是只有发生了改变效果就完全不一样了

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

  

  上面的例子可以看出区别,如果真的是引用传递,那么obj重新赋值,并且加上了name参数,最后person打印的应该是Greg的名字,但是结果却是原来的值,只能说明javascript在这里挖了一个大坑,非常的迷惑人,不过只要搞清楚这点就行了。

四、 执行环境及作用域

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

   全局执行环境是最外围的执行环境,在web浏览器中,其实就是window对象,因此,所有全局变量和函数,都是作为window的属性和方法创建的,某个执行环境所有代码执行完毕之后,该环境被销毁,保存在其中的变量和函数定义也随之被销毁(全局执行环境直到应用程序退出,及浏览器关闭的时候才会被销毁)

  每个函数都有自己的执行环境__,当程序执行到一个函数时,函数的环境会被创建出来,进入当前程序的流程,而在函数执行完成之后,程序流程将其弹出并销毁,把控制权返回给之前的执行环境

  当代码在一个环境中执行时,会创建变量对象的__作用域链__,其根本意义就是在不同层级的执行环境中,保证各个执行环境中的变量有序访问,看看下面的代码:

    var color = "blue";
    function changeColor(){
        var anotherColor = "red";
        function swapColors(){
            var tempColor = anotherColor;
            anotherColor = color;
            color = tempColor;
            //在 swapColors函数里面可以访问tempColor,anotherColor和color
        }
        //在这里可以访问anotherColor和color,但不能访问tempColor
        swapColors();
    }

  可以更形象的看看下面的图:

  通过列子和图,可以看出,内部环境可以通过作用域链访问它之上的所有外部环境,但是外部环境不能访问内部环境中的任何变量和函数。这些环境是线性的,有次序的。

  每个环境都可以向上搜索作用域链,以查询变量和函数名;而任何环境都不能通过向下搜索作用域链而进入另一个执行环境

  上面这段话非常重要,我们来看下例子:

    var color = "blue";
    function getColor(){
        return color;
    }
    alert(getColor());  //"blue"

  很明显,getColor函数里面的color变量是从里往外搜索到上级外部环境的color得到的,如图:

  在搜索的过程中,如果出现同名的局部变量,这个搜索就会停止:

    var color = "blue";
    function getColor(){
        var color = "red";
        return color;
    }
    alert(getColor());  //"red"

  

  函数从里往外执行

时间: 2024-08-08 09:25:43

JavaScript 变量的作用域的相关文章

PHP (20140510)深入浅出 JavaScript 变量、作用域和内存 v 0.5

深入浅出 JavaScript 变量.作用域和内存 v 0.5 本文主要从原理入手分享变量和作用域的相关知识,最后结合本文所分享知识,再次深入了解下闭包的运行原理. 主要参考<JS高级程序设计> <JS权威指南> <高性能 JS> 三本书. 目录 1 变量 1.1 变量的声明 1.2 变量类型的特点 2 执行环境和作用域 3 再谈谈闭包 变量 对 JavaScript 稍微有点了解的同学都知道,JavaScript 中的变量与其他语言的变量有很大区别. JS 的弱类型的

转:javascript变量的作用域

原文请访问http://www.cnblogs.com/rubylouvre/archive/2009/08/21/1551270.html, 我也只是为了做个记录 javascript变量的作用域 <script type="text/javascript">  var a=100;  var b=true;  function test(){      alert(a);      alert(b);      b=false;      alert(b);     

关于“javascript变量的作用域”的理解

*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin: 15px 0; } /* HEAD

【Python全栈-JavaScript】JavaScript变量的作用域

JavaScript变量的作用域全局变量 1.当在script中定义变量,在当前script中的定义前调用是undefined,没有定义该变量时调用报错.原因是在内存中开辟了该变量的存储位置,(当执行script时将所有定义的变量名先存到栈中) 当代码解释到该语句时才会将值存在栈中,没有执行之前调用该变量就是undefined,如果没有定义就不会在内存中开辟存储位置,因此就会报错. 2.如果在上一个script中调用下面的script的变量时,这时候不但没有值,而且没有开辟存储空间.因此,在上一

JavaScript 变量、作用域和内存问题

按照ECMA-262第三版的定义,JavaScript的变量与其他语言的变量有很大区别.JavaScript变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何种数据类型的规则,变量的值及其数据类型可以在脚本的生命周期内改变.尽管从某种角度看,这可能是一个既有趣又强大,同时又容易出问题的特性,但JavaScript变量实际的复杂程度还远不止如此. 1,基本类型和引用类型的值 ECMAScript变量可能包含两种不同类型的值:基本类型值和引用类

JavaScript变量、作用域和内存问题(一)

接下来博客的内容 理解基本类型和引用类型的值 理解执行环境 理解垃圾收集 按照 ECMA-262 的定义,JavaScript 的变量与其他语言的变量有很大区别.JavaScript 变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变.尽管从某种角度看,这可能是一个既有趣又强大,同时又容易出问题的特性,但 JavaScript 变量实际的复杂程度还远不止如此. 基本类型和引用

[从jQuery看JavaScript]-变量与作用域链

jQuery片段: [javascript] view plaincopy var // Will speed up references to window, and allows munging its name. window = this, // Will speed up references to undefined, and allows munging its name. undefined, // Map over jQuery in case of overwrite _jQ

深入浅出 JavaScript 变量、作用域和内存 v 0.5

本文主要从原理入手分享变量和作用域的相关知识,最后结合本文所分享知识,再次深入了解下闭包的运行原理. 主要参考<JS高级程序设计> <JS权威指南> <高性能 JS> 三本书. 目录 1 变量 1.1 变量的声明 1.2 变量类型的特点 2 执行环境和作用域 3 再谈谈闭包 变量 对 JavaScript 稍微有点了解的同学都知道,JavaScript 中的变量与其他语言的变量有很大区别. JS 的弱类型的特性决定了变量只是在特定时间(生命周期,作用域中)用于保存特定值

[label][JavaScript][The Defined Guide of JavaScript] 变量的作用域

变量的作用域 一个变量的作用域(scope)是程序中定义这个变量的区域. 全局(global)变量的作用域(scope)是全局性的,即在JavaScript代码中,它处处都有定义.    而在函数之内声明的变量,就只在函数体内部有定义,它们是局部(local)变量,作用域是局部性的.    函数的参数也是局部变量,它们只在函数体内部有定义.    在函数体内部,局部变量的优先级比同名的局部变量高.        如果给一个局部变量或函数的参数声明的名字与某个全局变量的名字相同,那么就有效地隐藏了

JavaScript变量、作用域和内存问题总结

㈠理解基本类型和引用类型的值  ⑴JavaScript变量可以用来保存两种类型的值:基本类型值和引用类型值. ⑵基本类型的值源自以下 5 种基本数据类型:Undefined.Null.Boolean.Number 和 String. ⑶基本类型值和引用类型值具 有以下特点: ? 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中: ? 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本: ? 引用类型的值是对象,保存在堆内存中: ? 包含引用类型值的变量实际上包含的并不是对象