zoukankan      html  css  js  c++  java
  • 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的值的复制,其实和普通函数是一样的,不要因为加了闭包就迷糊了,回归本源去思考就明白了,本源就是上面讲到的传址的传递


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

  • 相关阅读:
    WF4.0 Beta1 自定义跟踪
    WF4.0 Beta1 流程设计器与Activity Designer
    新版本工作流平台的 (二) 权限算法(组织结构部分)
    WF4.0 Beta1 WorkflowInvoker
    WF4.0 基础篇 (十) Collection 集合操作
    WF4.0 基础篇 (十五) TransactionScope 事物容器
    WF4.0 基础篇 (六) 数据的传递 Arguments 参数
    WF4B1 的Procedural Activity 之InvokeMethod , InvokeMethod<T> 使用
    WF4.0 Beta1 异常处理
    WF4.0 Beta1 变量 Variables
  • 原文地址:https://www.cnblogs.com/mitang/p/6709945.html
Copyright © 2011-2022 走看看