好像一般很少人讲到js中的引用和复制,不过弄清楚这个概念可以帮助理解很多东西

先讲一下很基础的东西,看看js中几种数据类型分别传的什么
引用:对象、数组、函数
复制:数字、布尔
字符串单独说明,因为它的特殊性,无法确定是传递引用还是复制数值(因为字符串的值是没法改变的,所以纠结这个问题也是没意义的)但是用于比较的时候显然是属于传值比较(稍后具体说比较的事)

下面讲一下在使用中的具体体现

最普通的使用就是赋值了
var a = 1;
var b = a;   //赋的是a的复制值
b ++;
alert(a);   //"1"   b的修改不影响a
/****************************************/
var a = [1];
var b = a;     //赋的是a的引用 
b[0] ++;
alert(a);  //"2"   b的修改对a也有效    不过当然b = [2];这种修改对a是没用的。。。。。。

函数的参数
传值的传递:传给函数的是数值的一个复制,函数中对其的修改外部不可见
var a = 1;
var b = 2;
function change(a,b) {
  var c = a;
  a = b;      //用新引用覆盖
  b = c;
  alert(a);   //"2"         
  alert(b);   //"1"
}
change(a,b);
alert(a);   //"1"         
alert(b);   //"2"
传址的传递:传给函数的是数值的一个引用,函数中对其属性的修改外部可见,但用新引用覆盖其则在外部不可见,比如
var a = [1, 2, 3];
var b = [5, 6];
function change(a,b) {
  a[0] = 4;    //对其属性的修改外部可见  
  var c = a;
  a = b;      //用新引用覆盖
  b = c;
  alert(a);   //"5,6"         
  alert(b);   //"4,2,3"
}
change(a,b);
alert(a);    //"4,2,3"
alert(b);     //"5,6"
从结果可以看出a和b并没有互换   因为用新引用覆盖在外部不可见 这个很自然 因为函数只是拿到了引用 并没有权力更改引用

下面这个就不同了
var a = [1, 2, 3];
var b = [5, 6];
function change() {
  var c = a;
  a[0] = 4;
  a = b;
  b = c;
};
change();
alert(a);   //"5,6"
alert(b);   //"4,2,3"
这里成功实现互换  
又得提到js的块级作用域了,这个放某些语言里定然是要报未定义错误的,因为js没有块级作用域,所以它在change里找不到变量a,b就会自觉的到上层去找,所以这里的a,b是全局变量的引用
而上面的那个a,b则是change函数中的变量,在调用函数时传递了a,b的引用赋给了这两个变量,但是并不能改变全局中的a,b,这里换个名字大概就好理解多了
这个稍微提下    有些走题了。。。。
回到引用和复制 在比较运算中的注意事项
传值的比较比较的是数值 而传址的比较比较的是引用,引用不同即使数值相同也不等
1 == 1;    //true
1 === 1;   //true
[0] == [0]; //false
[0][0] == [0][0];    //true
[0][0] === [0][0];   //true
[0].toString() == [0].toString();   //true    
 
闭包中。。。。
闭包大概是js中最纠结的东西 我们部门面试的经典试题,常考不衰啊。。。。
这里我先不说闭包的东西,只说一下涉及传值和引用的部分,等我哪天确定自己可以用清晰的条例、简明的语言、生动的实例彻底的说清楚那个东西,再详细介绍这个提js不能不提的家伙。。。
闭包中,内部函数用外部函数的局部变量使用引用的方式而不是复制
其实这也是理解闭包的一个很重要的部分 可以用这个解释一个很经典的闭包现象,很多地方在说明闭包的时候都会用到的一个例子
/*构造一个函数,给数组中的节点设置事件处理程序,当点击一个节点时,alert出节点的序号*/
var add_handlers = function (nodes) {
    var i;
    for (i = 0, l = nodes.length; i < l; i ++) {
        nodes[i].onclick = function (e) {
           alert(i);    // 当然这里的结果必然是每次alert的都是节点总数。。。。
        }
    }
};
为什么每次alert的都是节点总数 而不是预期的序号呢,这个如果用复制和引用解释就相当容易了
因为内部函数在使用外部变量时使用引用的方式而不是复制,就是说我给每个节点设置onclick事件的时候将i的引用传递给了alert,当我点击节点触发onclick事件的时候,i的值已经变成了节点总数。。。
var add_handlers = function (nodes) {
    var i;
    for (i = 0, l = nodes.length; i < l; i ++) {
 
        nodes[i].onclick = function (i) {
           return function(){
           alert(i);    
           }
 }(i);
    }
};
这样修改后之所以正确是因为此时传进去的是i的值的复制,其实和普通函数是一样的,不要因为加了闭包就迷糊了,回归本源去思考就明白了,本源就是上面讲到的传址的传递
顺便提一句,不要被闭包这个古怪的名字唬住了,其实它和我们平时用的函数原理是一样的,抛开那些“更长的生命周期”“保护私有变量”等闭包所谓的特性,把它当成一个普通的函数(也可以换个角度把全局函数看成一个特殊的闭包),很容易就可以理解了
关键是要放下所有的浮华,回归最本质。。。。。。又跑题了。。。。。。

js- 引用和复制(传值和传址)的更多相关文章

  1. 图解JS的传值与传址

    //编程过程中经常会碰到传值,传址的问题!今天的主题就是关于传值.与传址. //先讲讲赋值操作 //下例是原始类型赋值操作 var a=1,b=a,a=2; console.log("a=& ...

  2. 再谈js传值和传址

    js的传值和传址还是真绕,前回文说道 1.值类型是传值的 2.对象和数组是传址的 这两点通过例子的到了证实 然而还有一种情况没有讨论 即 函数的参数的传值和传址 通过实验,在函数中用一个新对象去覆盖传 ...

  3. javascript的变量,传值和传址,参数之间关系

    先把收获晾一下: 1.javascrip变量包含两种类型的值,一种为引用类型的值,一种是基本类型的值.引用类型包括:Array,Object,Function(可以这么理解,非基本类型的都是引用类型) ...

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

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

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

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

  6. Python 传值和传址 copy/deepcopy

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

  7. [javaSE] 变量的传值与传址

    变量:就是将不确定的数据进行存储.也就是需要在内存中开辟一个空间 这个空间需要一个名称,这个名称就是变量名 基本数据类型:byte,short,int,long,double,float,char,b ...

  8. JAVA传值与传址

    要了解JAVA中的传值与传址问题,必要先要了解JVA中的栈内存和堆内存,>>>>点些查看<<<<昨天写的学习记录 栈:基本数据类型.数据的引用变量,这两 ...

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

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

随机推荐

  1. MVC c# 调用sql的存储过程

    var hid = new SqlParameter { ParameterName = "HistoryId", Value = history.Id, Direction = ...

  2. ftp操作方法整理

    1.整理简化了下C#的ftp操作,方便使用    1.支持创建多级目录    2.批量删除    3.整个目录上传    4.整个目录删除    5.整个目录下载 2.调用方法展示, var ftp ...

  3. 巧用Scrum与Kanban

    本文来自网易云社区 文\屈鹏飞 在互联网行业的项目管理实践中,敏捷和精益一直是大家所提倡的思想,其中Scrum和Kanban方法作为即敏捷又精益的典型代表,许多PM都在研究,笔者近期也在学习和实施Sc ...

  4. 在ubuntu下安装KDE以及完全卸载KDE

    自由转载 ^_^ 同时请注明原文出处:http://www.cnblogs.com/wangvsa/archive/2012/07/22/2603626.html 这是一篇翻译,很多不必要的东西就没翻 ...

  5. 上课总结-数据结构c++

    class 1 数据结构就是指 按一定的逻辑结构组成的一批数据,使用某种存储结构将这批数据存储于计算机中,并在这些数据上定义了一个运算集合. 例1.煤气管道的铺设问题.如图需为城市的各小区之间铺设煤气 ...

  6. rabbitmq消息消费者

    pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:// ...

  7. File 文件操作类 大全

    File  文件操作类  大全 许多人都会对文件操作感到很难  我也是  但是一个好的项目中必定会涉及到文件操作的 文件的复制 粘贴  等等等 公司大佬写了 一个文件操作的工具类 感觉还是棒棒的啦   ...

  8. JSONP原理及简单实现 可做简单插件使用

    JSONP实现跨域通信的解决方案. 在jquery中,我们可以通过$.ajax的dataType设置为jsonp来调用jsonp,但是jsonp和ajax的实现原理一个关系都木有.jsonp主要是通过 ...

  9. Android 数据库框架GreenDao使用

    1.GreenDao3介绍 (1)基本概念 (2)GreenDao3工作原理 (3)GreenDao优点 (4)GreenDao3版本的改进 2.GreenDao3的相关配置概念介绍 (1)配置项目( ...

  10. RNA-seq分析htseq-count的使用

    HTSeq作为一款可以处理高通量数据的python包,由Simon Anders, Paul Theodor Pyl, Wolfgang Huber等人携手推出HTSeq — A Python fra ...