javascript变量的作用域

基本类型和引用类型


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

变量的赋值


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

var num1 = 5;

var num2 = num1;

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

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

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"

javascript变量的作用域的更多相关文章

  1. javascript 函数初探 (三)--- javascript 变量的作用域

    javascript 变量的作用域: 这是一个至关重要的问题.特别是当我们从别的语言转向javascript时,必须要明白一点,即在javascript中,变量的定义并不是以代码块作为作用域的,而是以 ...

  2. 深入理解 JavaScript 变量的作用域和作用域链

    一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...

  3. JavaScript变量和作用域

    认识JavaScript中的变量 JavaScript中的变量有两种类型,一种是基本类型.一种是引用类型. 基本数据类型:Defined,Null,Boolean,Number,String.注意St ...

  4. JavaScript变量的作用域和函数的作用域的区别

    变量作用域和函数作用域都涉及到变量值的变化,本文旨在让大家明白他们之间的区别 变量的作用域: 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接 ...

  5. JavaScript - 变量,作用域,内存

    JavaScript 变量可以用来保存两种类型的值:基本类型值和应用类型值.基本类型的值源自以下5种基本数据类型:Undefined.Null.Bollean.Number和String. 所有变量都 ...

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

    本文主要从原理入手分享变量和作用域的相关知识,最后结合本文所分享知识,再次深入了解下闭包的运行原理. 主要参考<JS高级程序设计> <JS权威指南> <高性能 JS> ...

  7. 【javascript 变量和作用域】

    今天学习了javascript 的变量和作用域的基本知识,对于以前在开发中遇到的一些不懂的小问题也有了系统的认识,收获还是比较多的. [基本类型和引用类型] ECMAScript 变量可能包含两种不同 ...

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

    jQuery片段: var // Will speed up references to window, and allows munging its name. window = this, //  ...

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

    变量的作用域 一个变量的作用域(scope)是程序中定义这个变量的区域. 全局(global)变量的作用域(scope)是全局性的,即在JavaScript代码中,它处处都有定义.    而在函数之内 ...

随机推荐

  1. python print及格式化

    print(value,sep=' ',end='\n',file=sys.stdout, flush=False) sep=' '默认空格 print('hello','world') #hello ...

  2. Solr4.0 如何配置使用UUID自动生成id值

    原文链接http://blog.csdn.net/keepthinking_/article/details/8501058#comments 最近学习了Lucene,随便也学习了Solr,Solr规 ...

  3. c++顺序表基本功能

    头文件 #define LIST_MAX_SIZE 5#define LISTINCREMENT 2#include<assert.h>#include<string>temp ...

  4. java代理类及AOP

    1.代理架构图 2.AOP 3.动态代理概念 4.动态代理工作原理图

  5. Java笔记:文件夹操作

    创建目录: File类中有两个方法可以用来创建文件夹: mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false.失败表明File对象指定的路径已经存在,或者由于整个路径还不存在, ...

  6. Web应用性能优化思路

    瓶颈是什么? 一条4车道的公路,运行非常顺畅,突然出了点事故,事故车导致某个地方只剩下1车道,然后就开始堵车,因为四辆车同时塞向一个车道里.把这个事故清除了,故障车拖走了,道路会开始恢复了通畅. 这个 ...

  7. 51nod1183(Edit Distance)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1183 题意:中文题啦- 思路:dp 用dp[i][j]表示从 ...

  8. Docker(一)

    Docker是一个能够把开发的应用程序自动部署到容器的开源引擎,它基于Apache2.0开源授权协议发行,以Docker容器为资源分割和调度的基本单位,封装整个软件运行时环境,为开发者和管理员设计的, ...

  9. leetcode 137[转]

    没思路.网上找到的. 1. 将每一个int看成32位数,统计每一位出现的次数对3取余,所以需要开辟一个32大小的数组来统计每一位出现的次数 2. 对第一种思路进行简化,模拟3进制: three two ...

  10. Linux C编程学习之开发工具2---GDB调试器

    简介 GDB是一个功能强大的交互式程序调试工具,主要工作在字符界面下. GDB不仅可以用来调试C/C++ 语言编写的程序,还可以用来调试 Pascal.Objective-C,以及Fortran等语言 ...