zoukankan      html  css  js  c++  java
  • javascript变量的作用域

    基本类型和引用类型

    基本类型值指的是简单的数据段,而引用类型值指的是那个可能由多个值组成的对象

    讲一个值赋值给变量时,javascript解析器首先要确定是基本类型还是引用类型,基本数据类型可以直接操作保存在变量中的值,而引用数据类型的值是保存在内存中的对象,在操作对象是,实际上操作的是对象的引用而不是实际的对象

    变量的赋值

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

    来看下例子: 

    javascript

    var num1 = 5;

    var num2 = num1;

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

    这是基本数据类型,而引用类型呢?其实同样会将原来变量上的值复制一份到新的变量当中,只不过,复制的其实是原来变量的一个指针,而这个指针指向存储在堆中的一个对象。

    复制完成后,两个变量都指向了堆中的同一个对象,所以改变其中一个的值,会对另外一个产生影响。

    有以下代码
    javascript

    var obj1 = new Object();

    var obj2 = obj1;

    obj1.name = "Nicholas";

    alert(obj2.name);

    //"Nicholas"

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

     

    传递参数

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

    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在传递引用类型的参数的时候,只要这个参数不发生改变,那么还是按照引用类型来处理,但是只有发生了改变效果就完全不一样了 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的属性和方法创建的,某个执行环境所有代码执行完毕之后,该环境被销毁,保存在其中的变量和函数定义也随之被销毁(全局执行环境直到应用程序退出,及浏览器关闭的时候才会被销毁)

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

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

    看看下面的javascript

    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();

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

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

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

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

     javascript

    var color = "blue";

    function getColor(){

    return color;

    }

    alert(getColor());

    //"blue" 

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

    javascript

    var color = "blue";

    function getColor(){

    var color = "red";

    return color;

    }

    alert(getColor());

    //"red"

  • 相关阅读:
    波段是金牢记六大诀窍
    zk kafka mariadb scala flink integration
    Oracle 体系结构详解
    图解 Database Buffer Cache 内部原理(二)
    SQL Server 字符集介绍及修改方法演示
    SQL Server 2012 备份与还原详解
    SQL Server 2012 查询数据库中所有表的名称和行数
    SQL Server 2012 查询数据库中表格主键信息
    SQL Server 2012 查询数据库中所有表的索引信息
    图解 Database Buffer Cache 内部原理(一)
  • 原文地址:https://www.cnblogs.com/zouyajun/p/4090466.html
Copyright © 2011-2022 走看看