先把收获晾一下:

1.javascrip变量包含两种类型的值,一种为引用类型的值,一种是基本类型的值。引用类型包括:Array,Object,Function(可以这么理解,非基本类型的都是引用类型);5种基本类型包括:undefined,null,string,boolean,number

2.函数的参数的传递的机制是复制变量值。

书上说:”把函数外部的值复制给函数内部的参数,就和把值从一个变量复制给另一个变量一样。基本类型的传递如同基本类型变量的复制一样,而引用类型的则如同引用类型变量的复制一样。“

”当一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此改变其中一个变量,就会影响到另一个变量。“

【注意:复制引用类型的值,才是传址】

3.参数实际上是函数的局部变量。

----------------------------------------------------------------------------

基本概念的解释:

传值:把A的数值传到B,改变B,A不会跟着变,B存的是跟A一样的值;
传址:把A的地址传到B,改变B,A同时跟着变,B存的只是A的地址(类似电脑的快捷方式)。

一个具有值类型(value type)的数据存放在栈内的一个变量中。即是在栈中分配内存空间,直接存储所包含的值,其值就代表数据本身。值类型的数据具有较快的存取速度。

一个具有引用类型(reference type)的数据并不驻留在栈中,而是存储于堆中。即是在堆中分配内存空间,不直接存储所包含的值,而是指向所要存储的值,其值代表的是所指向的地址。当访问一个具有引用类型的数据时,需要到栈中检查变量的内容,该变量引用堆中的一个实际数据。引用类型的数据比值类型的数据具有更大的存储规模和较低的访问速度。

----------------------------------------------------------------------------

下面是三个问题。

【问题1】:为什么change(a)函数执行完之后,外面的a没有受干扰呢?

<script>
var a = [1, 2, 3];
function change(a) {
console.log(a);//[1,2,3]
a = 2; //传值
console.log(a);//2
}
change(a);
console.log(a); //[1,2,3]
</script>

问题1解答:因为change(a)的执行过程是这样的,首先将对象a(数组)传入到change以后,被复制给change的参数a。而后a=2是一个赋值语句,变成传值。此时a=2是值类型,并不涉及引用地址的问题。所以并没有影响外部的a。

【问题2】:为什么change(a)函数执行完之后,外面的a受到干扰呢?

<script>
var a = [1, 2, 3];
function change() {
a = 2;//传值
}
change();
console.log(a); //2
</script>

问题2解答:当执行change()的时候,函数在自己的执行环境中找寻作用域链,活动对象(activation object)并不包含变量a,于是沿着作用域链向上找,找到全局执行环境,发现变量a,于是此时函数内部的a和外部a在内存上是同一个地址,自然函数内部a变了,外部也会跟着变。

解析:问题2和问题1的区别在于,问题2并没有引入参数,所以不涉及复制变量的事情。

【问题3】:为什么change(a)函数执行完之后,外面的a受到干扰呢?

<script>
var a = [1, 2, 3];
function change(b) {
b[0] = 2;
}
change(a);
console.log(a); //[2,2,3]
</script>

问题3解答:这个和问题1非常类似,唯独不一样的就是a=2,换成了b[0]=2,我一开始也很疑惑,不说复制吗?参数b应该是个复制值,怎么会影响到外面的a呢?

的确,change函数执行时,参数b是a的复制值。因为a是引用类型,所以在函数内部是b和a按引用来访问的是一个地址的对象。b[0]=2的出现,并不影响在函数内部b和a引用的是同一个对象。

【问题4】:为什么change(a)函数执行完之后,外面的a没有受到干扰呢?

 var a = [1, 2, 3];
function change(b) {
console.log(b);//[1,2,3]
b=2;
b[0] = 2;
}
change(a);
console.log(a); //[1,2,3]

问题4解答:change(b)执行过程是这样的,a对象传入change函数,将值和地址复制给b。b=2这句,此时b变成值类型了,并不涉及地址引用的问题,之后b[0]=2这句实际上毫无意义,因为此时b已经不是数组了,自然不具有b[0]这样的索引方式。所以b与a的地址引用关系其实在b=2之后就消失了。此时外界的a仍然是[1,2,3];

参考书籍:

《Javascript高级程序设计(第3版)》

js- 引用和复制(传值和传址)http://blog.csdn.net/zzzaquarius/article/details/4902235

javascript的变量,传值和传址,参数之间关系的更多相关文章

  1. javascript . 05 json的组成、for...in 遍历对象、简单数据类型与复杂数据类型的传值与传址、内置对象

    对象字面量  JSON var obj = { aaa :999}; var json={"aaa":999,"bbb":888}; "kay&quo ...

  2. 工控随笔_18_西门子_WinCC的VBS脚本_07_变量作用域和传值、传址

    在vbs脚本中也存在和其他编程语言一样的概念,那就是变量的作用域,变量的作用域决 定在什么范围内可以访问. 同样的在vbs脚本中对于变量也有一个生命周期, 变量的生命周期决定了变量的存续时间 这个主要 ...

  3. Java方法传递参数传值还是传址的问题

    这几天重构项目代码遇到一个疑问:可不可以在方法A中定义一个boolean变量b为false,然后A调用方法C把b传递到C方法中经过一些列业务判断后修改为true,C执行结束后A方法中b的值还是原来的f ...

  4. Python的传值和传址与copy和deepcopy

    1.传值和传址 传值就是传入一个参数的值,传址就是传入一个参数的地址,也就是内存的地址(相当于指针).他们的区别是如果函数里面对传入的参数重新赋值,函数外的全局变量是否相应改变,用传值传入的参数是不会 ...

  5. java方法中,传参是传值还是传址问题(对比C语言、C#和C++)

    问题引出: 编写一个简单的交换值的小程序,如果我们只是简单地定义一个交换函数接收两个数,在函数内部定义一个中间变量完成交换.那么当我们把a,b两个实参传给这个函数时,往往得不到预期的结果.这是为什么呢 ...

  6. Python 传值和传址 copy/deepcopy

    传值:被调函数局部变量改变不会影响主调函数局部变量 传址:被调函数局部变量改变会影响主调函数局部变量 Python参数传递方式:传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组则传值:如 ...

  7. js- 引用和复制(传值和传址)

    js- 引用和复制(传值和传址) 好像一般很少人讲到js中的引用和复制,不过弄清楚这个概念可以帮助理解很多东西 先讲一下很基础的东西,看看js中几种数据类型分别传的什么引用:对象.数组.函数复制:数字 ...

  8. C# 函数的传值与传址(转)

    http://www.cnblogs.com/mdnx/archive/2012/09/04/2671060.html using System; using System.Collections.G ...

  9. Java传值和传址

    调用函数时,传的参数过去可能是传值,也可能是传址.如果是传值,函数内部的操作对参数的值没有影响:如果是传址,函数内部的操作是对参数指向的内存进行操作,会影响参数的值. Java到底是传值还是传址?用下 ...

随机推荐

  1. uWSGI其三:uWSGI搭配Nginx使用

    http://www.nowamagic.net/academy/detail/1330334 上一篇介绍了 uWSGI 来部署 Django 程序,但在在生产环境中单单只有 uWSGI 是不够的,N ...

  2. AdapterView的相关知识。

    AdapterView集成自ViewGroup,他的主要子类有AbsListView(Listview,GridView),AbsSpinner(Spinner,Gallery). AdapterVi ...

  3. ETL,ESB,BPM为什么要这些图形

    ==================================== ETL模式架构:(ECCD架构) 捕获增量数据进行数据同步 ESB模式架构: 基于SOA以及工作流,通过适配器接入 BPM架构 ...

  4. 无法加载程序集,因为该程序集包含EdmSchemaAttribute,并按名称加载结束类型。不允许同时按名称和特性进行加载

    小小记录下,今天写程序时遇到的一个bug,相信大家用MVC+EF写项目时遇到的概率是挺大的.昨天本人也遇到了,很悲剧,暂时没想到好的办法解决,跟项目经理交流了下,这个问题认为出现在EF的自身设计上,它 ...

  5. linux多线程

    #include <pthread.h> pthread_t pid; pthread_create(&pid, 0, pFunc, pArgs); //创建线程(linux下线程 ...

  6. MongoDB基本操作命令

    由于工作需要,笔者这两天使用了一下MongoDB.真的很不习惯!但是确实好用,命令比mysql和sqlserver简单很多.在这里整理一些MongoDB的基本操作命令分享出来. 客户端的安装就不说了, ...

  7. 深度解析国内O2O模式

    今日在网上发现这篇文章很棒,详细的分析了当前BAT矩阵下的o2o 的模式.所以转载过来与大家一起分享. 文章来自于:http://www.siilu.com/20151214/158917.shtml ...

  8. 慕课网-安卓工程师初养成-4-9 Java循环语句之 for

    来源:http://www.imooc.com/code/1425 Java 的循环结构中除了 while 和 do...while 外,还有 for 循环,三种循环可以相互替换. 语法: 执行过程: ...

  9. 慕课网-安卓工程师初养成-2-7 Java中变量的使用规则

    来源:http://www.imooc.com/code/1242 不得不接受的变量小脾气: 1.Java 中的变量需要先声明后使用 2.变量使用时,可以声明变量的同时进行初始化,也可以先声明后赋值 ...

  10. 学习记录 Java常见的几种字符集以及对 AscII的了解

     1.ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte). ...