2016-02-13 89 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