• js 引用和复制(传值和传址)


    http://blog.csdn.net/zzzaquarius/article/details/4902235

    好像一般很少人讲到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并没有互换   因为用新引用覆盖在外部不可见 这个很自然 因为函数只是拿到了引用 并没有权力更改引用

    引用和复制 在比较运算中的注意事项
    传值的比较比较的是数值 而传址的比较比较的是引用,引用不同即使数值相同也不等

    1 == 1;    //true
    1 === 1;   //true
    [0] == [0]; //false
    [0][0] == [0][0];    //true
    [0][0] === [0][0];   //true
    [0].toString() == [0].toString();   //true   

    闭包
    闭包中,内部函数用外部函数的局部变量使用引用的方式而不是复制
    其实这也是理解闭包的一个很重要的部分 可以用这个解释一个很经典的闭包现象,很多地方在说明闭包的时候都会用到的一个例子


    /*构造一个函数,给数组中的节点设置事件处理程序,当点击一个节点时,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的值的复制,其实和普通函数是一样的,不要因为加了闭包就迷糊了,回归本源去思考就明白了,本源就是上面讲到的传址的传递


    顺便提一句,不要被闭包这个古怪的名字唬住了,其实它和我们平时用的函数原理是一样的,抛开那些“更长的生命周期”“保护私有变量”等闭包所谓的特性,把它当成一个普通的函数(也可以换个角度把全局函数看成一个特殊的闭包),很容易就可以理解了

  • 相关阅读:
    CentOS6.5 mini安装到VirtualBox虚拟机中
    docker配置redis6.0.5集群
    docker搭建数据库高可用方案PXC
    我通过调试ConcurrentLinkedQueue发现一个IDEA的小虫子(bug), vscode复现, eclipse毫无问题
    ThreadLocal底层原理学习
    第九章
    多线程-java并发编程实战笔记
    Spring-IOC源码解读3-依赖注入
    Spring-IOC源码解读2.3-BeanDefinition的注册
    Spring-IOC源码解读2.2-BeanDefinition的载入和解析过程
  • 原文地址:https://www.cnblogs.com/mitang/p/6709945.html
Copyright © 2020-2023  润新知