2016-02-13 37 views
0

比方说阵列样机已经增加了一些辅助函数后数组的键:方法显示为深克隆与jQuery.extend

Array.prototype.doSomething = function() { ... } 

当我注销一个简单的数组到控制台...

console.dir([1,2,3]); 

...我得到:

Array [3] 
    0: 1 
    1: 2 
    2: 3 
    length: 3 
    __proto__: Array[0] 
     doSomething: function() 

一切正常为止。

但只要我深克隆使用$ .extend阵列(深克隆,因为我的实际数据是比较复杂的 - 用数组作为属性的对象,但在任何情况下发生的)...

$.extend(true, [], [1,2,3]); 

我突然得到:

Array [3] 
    0: 1 
    1: 2 
    2: 3 
    doSomething: function()  // ??? 
    length: 3 
    __proto__: Array[0] 
     doSomething: function() 

它看起来像原型方法已被添加为数组实例的实际项目。

在复制之前,JQuery.extend没有测试hasOwnProperty()吗?或者我在这里做错了什么?

+1

是的,但是你也做错了,请参阅[如何在Array.prototype和Object.prototype上定义javascript方法,以便它不出现在循环中](http:// stackoverflow .com/q/13296340/1048572) – Bergi

回答

1

不JQuery.extend不测试hasOwnProperty()复制

没有之前不会。从源代码使用for ... in循环遍历所有被克隆的属性,但在设置属性之前不会执行hasOwnProperty检查。

https://github.com/jquery/jquery/blob/7103d8ef47e04a4cf373abee0e8bfa9062fd616f/src/core.js#L120

jQuery.extend = jQuery.fn.extend = function() { 
    var options, name, src, copy, copyIsArray, clone, 
     target = arguments[ 0 ] || {}, 
     i = 1, 
     length = arguments.length, 
     deep = false; 

    // Handle a deep copy situation 
    if (typeof target === "boolean") { 
     deep = target; 

     // Skip the boolean and the target 
     target = arguments[ i ] || {}; 
     i++; 
    } 

    // Handle case when target is a string or something (possible in deep copy) 
    if (typeof target !== "object" && !jQuery.isFunction(target)) { 
     target = {}; 
    } 

    // Extend jQuery itself if only one argument is passed 
    if (i === length) { 
     target = this; 
     i--; 
    } 

    for (; i < length; i++) { 

     // Only deal with non-null/undefined values 
     if ((options = arguments[ i ]) != null) { 

      // Extend the base object 
      for (name in options) { 
       src = target[ name ]; 
       copy = options[ name ]; 

       // Prevent never-ending loop 
       if (target === copy) { 
        continue; 
       } 

       // Recurse if we're merging plain objects or arrays 
       if (deep && copy && (jQuery.isPlainObject(copy) || 
        (copyIsArray = jQuery.isArray(copy)))) { 

        if (copyIsArray) { 
         copyIsArray = false; 
         clone = src && jQuery.isArray(src) ? src : []; 

        } else { 
         clone = src && jQuery.isPlainObject(src) ? src : {}; 
        } 

        // Never move original objects, clone them 
        target[ name ] = jQuery.extend(deep, clone, copy); 

       // Don't bring in undefined values 
       } else if (copy !== undefined) { 
        target[ name ] = copy; 
       } 
      } 
     } 
    } 

    // Return the modified object 
    return target; 
}; 

是否影响你的阵列中的数据?取决于你如何使用数组可能不是。迭代数组元素仍然是一样的,只要你使用正确的循环过程。含义for(;;)for ... of.forEach。而做JSON.stringify仍然会给你正确的JSON。

+0

谢谢!不,它不影响数据,当我查看控制台输出时,它只是感觉错误。我猜他们为了性能原因省略了hasOwnProperty检查? 如果我将'Object.defineProperty()'与'enumerable'设置为false以将该方法添加到Array.prototype,它会起作用吗? – subarachnid

+0

要回答我自己的问题,它似乎以这种方式工作'Object.defineProperty(Array。原型,“doSomething”,{enumerable:false,...});' – subarachnid