Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does jQuery Extend Deep Copy not recursively copy an object?

I've searched everywhere and found similar questions with answers that didn't really address my issue so I apologize if this seems like a repeat, but it appears from my experimenting that jQuery's deep copy function doesn't actually work as it's described (or maybe I'm misreading its description).

Here's an example demonstrating the problem I'm having: http://jsfiddle.net/wcYsH/

Or this for download: https://github.com/kevroy314/jQuery-Extend-Test

Why does the data in the previous copy get changed when the deep copy is manipulated?

like image 673
user986122 Avatar asked May 08 '12 19:05

user986122


People also ask

How do you make a deep copy of nested objects?

assign() was the most popular way to deep copy an object. Object. assign() will copy everything into the new object, including any functions. Mutating the copied object also doesn't affect the original object.

Is object create deep copy?

Object. assign does not copy prototype properties and methods. This method does not create a deep copy of Source Object, it makes a shallow copy of the data. For the properties containing reference or complex data, the reference is copied to the destination object, instead of creating a separate object.

Does JavaScript do deep copy?

Copying a value in JavaScript is almost always shallow, as opposed to deep. That means that changes to deeply nested values will be visible in the copy as well as the original.

What is deep cloning JavaScript?

A deep copy is a copy of all elements of the original object. Changes made to the original object will not be reflected in the copy. In this article, you will create deep copies of objects using the Lodash library.


Video Answer


1 Answers

For one, you aren't creating normal objects.

I'm looking at the source code for jQuery 1.7.2 for extend.

https://github.com/jquery/jquery/blob/master/src/core.js

And I'm noticing the line:

if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy))

has to evaluate to true to do deep copying. copy is just part of the current object being copied.

But you aren't creating "plain" objects. You are creating objects generated by invoking a constructor with the new operator.

Now, in isPlainObject, it seems these lines have to be evaluated. (where hasOwn is hasOwn = Object.prototype.hasOwnProperty

    try {
        // Not own constructor property must be Object
        if ( obj.constructor &&
            !hasOwn.call(obj, "constructor") &&
            !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
            return false;
        }
    } catch ( e ) {
        // IE8,9 Will throw exceptions on certain host objects #9897
        return false;
    }

And there's where it concludes it's not a "plainObject".

This makes sense when you consider objects with a constructor probably ought to be created via that constructor or at least use some sort of "clone" method as you'd see in other languages/frameworks.

like image 90
JayC Avatar answered Oct 21 '22 03:10

JayC