zoukankan      html  css  js  c++  java
  • javascript深拷贝

    貌似我博客还有另外两个类似的函数,不过年代比较久远了,随着我技术的提高,更好的函数被创造出来。突然问起我以前的函数,我也会愣一下,心想,真烂!我总是喜欢把最好的东西分享给大家的,以前的大家忘掉吧。

    我们先看一下浅复制的缺陷,不知多少人中过招呢?

          var oOriginal = {
            memNum: 1,                                      // number
            memStr: "I am a string",                      // string
            memObj: {
              test1: "Old value"                              // we’ll test
            },
            memArr: [                                         // array 
              "a string",                                       // string member of array
              {                                                   // object member of array
                test2: "Try changing me"                 // we'll test
              }
            ]
          };
    

    这是一个比较复杂的对象,对象包含着对象与数组。我们用Prototype著名的继承函数复杂一下。它那个东东实在很难说是继承,jQuery的也不算。

          var extend = function(result, source) {
            for (var key in source)
              result[key] = source[key];
            return result;
          }
    

    测试程序:

          var oCopy = extend({},oOriginal);                     // 浅拷贝
          oCopy.memObj.test1 = "New value";                     // 出现问题了,会反射到原对象上
          alert(oOriginal.memObj.test1);                        // 结果副本与原本都一同被修改了
          oCopy.memArr[1].test2 = "I am changed";              
          alert(oOriginal.memArr[1].test2);                      // 同样中招了
    

    看来如果不想修改原对象,我们需要特殊处理一下对象与数组。为了处理它们,我们就必须把它们识别出来。看下面函数:

          /**
           * type identification - By 司徒正美::cheng (MIT Licensed)
           * http://www.cnblogs.com/rubylouvre/archive/2010/01/20/1652646.html
           */
            var is = function (obj,type) {
            var toString = Object.prototype.toString,undefined;
            return (type === "Null" && obj === null) ||
              (type === "Undefined" && obj === undefined ) ||
              toString.call(obj).slice(8,-1) === type;
          };
    

    上面的函数是用于进行类型识别的,typeof是不可靠的,Array会返回"object",instanceof也不行,它无法判定另一个文档对象的Array实例。利用Object.prototype.toString.call虽然不是尽善尽美,鸭子类型嘛,很容易仿造,但总比以前的靠谱多了。

    下面正式进入主题,我们的深拷贝函数会特殊处理值为对象与数组的键值对,对于它们,程序会为目标对象先创建一个新对象与数组,然后再一层层拷下去。我们可以看到它并没有用hasOwnProperty,换言之,连原型中可遍历的属性都给它翻个底朝天。对于数组,我们不用for(,,,)循环,它只能循环括号中的元素,无法循环附在数组上的其他属性,因此这里还是需要for...in这个特慢的方法。由于深拷贝把所有属性都进行检测,中间还可能创建新对象,因此是个巨重型的方法。无事就别用。

    /**
     * type identification - By 司徒正美::cheng (MIT Licensed)
     * http://www.cnblogs.com/rubylouvre/archive/2010/03/26/1696600.html
     */
    
          dom.deepCopy = function(result, source){
            for(var key in source) {
              var copy = source[key];
              if(source === copy) continue;//如window.window === window,会陷入死循环,需要处理一下
              if(dom.is(copy,"Object")){
                result[key] = arguments.callee(result[key] || {}, copy);
              }else if(dom.is(copy,"Array")){
                result[key] = arguments.callee(result[key] || [], copy);
              }else{
                result[key] = copy;
              }
            }
            return result;
          };
    

  • 相关阅读:
    Windows Azure Web Site (19) Azure Web App链接到VSTS
    Windows Azure Virtual Machine (35) Azure VM通过Linked DB,执行SQL Job
    Azure PowerShell (16) 并行开关机Azure ARM VM
    Windows Azure Virtual Network (12) 虚拟网络之间点对点连接VNet Peering
    Azure ARM (21) Azure订阅的两种管理模式
    Windows Azure Platform Introduction (14) 申请海外的Windows Azure账户
    Azure ARM (20) 将非托管磁盘虚拟机(Unmanage Disk),迁移成托管磁盘虚拟机(Manage Disk)
    Azure ARM (19) 将传统的ASM VM迁移到ARM VM (2)
    Azure ARM (18) 将传统的ASM VM迁移到ARM VM (1)
    Azure Automation (6) 执行Azure SQL Job
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1696600.html
Copyright © 2011-2022 走看看