Skip to content

Instantly share code, notes, and snippets.

@dysfunc
Last active March 2, 2017 01:30
Show Gist options
  • Save dysfunc/9701950 to your computer and use it in GitHub Desktop.
Save dysfunc/9701950 to your computer and use it in GitHub Desktop.

Revisions

  1. dysfunc revised this gist Oct 21, 2015. No changes.
  2. dysfunc revised this gist Oct 8, 2015. 1 changed file with 28 additions and 11 deletions.
    39 changes: 28 additions & 11 deletions angular-deep-extend.js
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,21 @@
    /**
    * Deep copy example:
    * var deep = angular.extend(true, { hello: 'world', app: { id: '1234', groups: [{ id: 1},2,3,4,5] }, ids: [1,2,3] }, { app: { name: 'bond', groups: [6, 7, {hello:'world', test: [1,2,3,4, [12,34,45]]}, 9] }, ids: [4,5,6] });
    * angular.extend(true, { hello: 'world', app: { id: '1234', groups: [{ id: 1},2,3,4,5] }, ids: [1,2,3] }, { app: { name: 'bond', groups: [6, 7, {hello:'world', test: [1,2,3,4, [12,34,45]]}, 9] }, ids: [4,5,6,3] });
    * => "{"hello":"world","app":{"id":"1234","groups":[{"id":1},2,3,4,5,6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9],"name":"bond"},"ids":[1,2,3,4,5,6,3]}"
    *
    * Deep copy and dedup arrays
    * angular.extend(true, true, { hello: 'world', app: { id: '1234', groups: [{ id: 1},2,3,4,5] }, ids: [1,2,3] }, { app: { name: 'bond', groups: [6, 7, {hello:'world', test: [1,2,3,4, [12,34,45]]}, 9] }, ids: [4,5,6,3] });
    * => "{"hello":"world","app":{"id":"1234","groups":[{"id":1},2,3,4,5,6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9],"name":"bond"},"ids":[1,2,3,4,5,6]}"
    *
    * vs jQuery
    *
    * vs jQuery deep copy
    * jQuery.extend(true, { hello: 'world', app: { id: '1234', groups: [{ id: 1},2,3,4,5] }, ids: [1,2,3] }, { app: { name: 'bond', groups: [6, 7, {hello:'world', test: [1,2,3,4, [12,34,45]]}, 9] }, ids: [4,5,6,3] });
    * => {"hello":"world","app":{"id":"1234","groups":[6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9,5],"name":"bond"},"ids":[4,5,6]}"
    *
    * Shallow copy: (same as everyone else)
    * var shallow = angular.extend({ hello: [1,2,3,4] },{ hello: [5,6,7,8] })
    * angular.extend({ hello: [1,2,3,4] },{ hello: [5,6,7,8] })
    * => "{"hello":[5,6,7,8]}"
    */

    /*
    * Determine whether an Object is a plain object or not (created using "{}" or "new Object")
    * @param {Object} obj Object we want to check
    @@ -46,17 +51,25 @@ angular.unique = function(array){
    * @param {Object} arguments One or more additional objects to merge with the first
    * @return {Object} The target object with the new contents
    *
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    * angular.extend(true, true, object, object2) // deep copy + dedup arrays
    */
    angular.extend = function(target){
    angular.extend = function(target){
    var i = 1,
    deep = false;
    deep = false,
    dedup = false;

    if(typeof(target) === 'boolean'){
    deep = target;
    target = arguments[1] || {};
    i++;

    if(typeof(target) === 'boolean'){
    dedup = target;
    target = arguments[2] || {};
    i++;
    }
    }

    [].slice.call(arguments, i).forEach(function(obj){
    @@ -67,7 +80,7 @@ angular.extend = function(target){
    }

    if(deep && obj instanceof Array){
    target = angular.unique(target.concat(obj));
    target = dedup ? angular.unique(target.concat(obj)) : target.concat(obj);
    }
    else{
    for(var key in obj){
    @@ -87,7 +100,11 @@ angular.extend = function(target){

    isArray = false;

    target[key] = angular.extend(deep, clone, copy);
    if(dedup){
    target[key] = angular.extend(deep, dedup, clone, copy);
    }else{
    target[key] = angular.extend(deep, clone, copy);
    }
    }
    else if(copy !== undefined){
    target[key] = copy;
  3. dysfunc revised this gist Oct 2, 2015. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions angular-deep-extend.js
    Original file line number Diff line number Diff line change
    @@ -4,10 +4,9 @@
    * => "{"hello":"world","app":{"id":"1234","groups":[{"id":1},2,3,4,5,6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9],"name":"bond"},"ids":[1,2,3,4,5,6]}"
    *
    * vs jQuery
    *
    * => {"hello":"world","app":{"id":"1234","groups":[6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9,5],"name":"bond"},"ids":[4,5,6]}"
    *
    * Shallow copy:
    * Shallow copy: (same as everyone else)
    * var shallow = angular.extend({ hello: [1,2,3,4] },{ hello: [5,6,7,8] })
    * => "{"hello":[5,6,7,8]}"
    */
  4. dysfunc revised this gist Oct 2, 2015. 1 changed file with 75 additions and 34 deletions.
    109 changes: 75 additions & 34 deletions angular-deep-extend.js
    Original file line number Diff line number Diff line change
    @@ -1,35 +1,76 @@
    /**
    * Determine whether an Object is a plain object or not (created using "{}" or "new Object")
    * @param {Object} obj Object we want to check
    * @return {Boolean} True/False result
    */
    angular.isPlainObject = function(obj){
    return !(typeof(obj) !== 'object' || obj && obj.nodeType || obj !== null && obj === obj.window || obj && obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf'));
    };

    /**
    * Merge the contents of two or more objects into the target object
    * @param {Boolean} deep If true, the merge becomes recursive (optional)
    * @param {Object} target The object receiving the new properties
    * @param {Object} arguments One or more additional objects to merge with the first
    * @return {Object} The target object with the new contents
    *
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    */
    angular.extend = function(target){
    var i = 1,
    deep = false;

    if(typeof(target) === 'boolean'){
    deep = target;
    target = arguments[1] || {};
    i++;
    /**
    * Deep copy example:
    * var deep = angular.extend(true, { hello: 'world', app: { id: '1234', groups: [{ id: 1},2,3,4,5] }, ids: [1,2,3] }, { app: { name: 'bond', groups: [6, 7, {hello:'world', test: [1,2,3,4, [12,34,45]]}, 9] }, ids: [4,5,6] });
    * => "{"hello":"world","app":{"id":"1234","groups":[{"id":1},2,3,4,5,6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9],"name":"bond"},"ids":[1,2,3,4,5,6]}"
    *
    * vs jQuery
    *
    * => {"hello":"world","app":{"id":"1234","groups":[6,7,{"hello":"world","test":[1,2,3,4,[12,34,45]]},9,5],"name":"bond"},"ids":[4,5,6]}"
    *
    * Shallow copy:
    * var shallow = angular.extend({ hello: [1,2,3,4] },{ hello: [5,6,7,8] })
    * => "{"hello":[5,6,7,8]}"
    */

    /*
    * Determine whether an Object is a plain object or not (created using "{}" or "new Object")
    * @param {Object} obj Object we want to check
    * @return {Boolean} True/False result
    */
    angular.isPlainObject = function(obj){
    return !(typeof(obj) !== 'object' || obj && obj.nodeType || obj !== null && obj === obj.window || obj && obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf'));
    };

    /**
    * Removes duplicates from an Array
    * @param {Array} Array Array to dedup
    * @return {Array} Array containing only unique values
    */
    angular.unique = function(array){
    var a = array.concat();

    for(var i = 0; i < a.length; ++i){
    for(var j = i + 1; j < a.length; ++j){
    if(a[i] === a[j]){
    a.splice(j--, 1);
    }
    }
    }

    return a;
    };

    /**
    * Merge the contents of two or more objects into the target object
    * @param {Boolean} deep If true, the merge becomes recursive (optional)
    * @param {Object} target The object receiving the new properties
    * @param {Object} arguments One or more additional objects to merge with the first
    * @return {Object} The target object with the new contents
    *
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    */
    angular.extend = function(target){
    var i = 1,
    deep = false;

    angular.forEach([].slice.call(arguments, i), function(obj){
    var src, copy, isArray, clone;
    if(typeof(target) === 'boolean'){
    deep = target;
    target = arguments[1] || {};
    i++;
    }

    [].slice.call(arguments, i).forEach(function(obj){
    var src, copy, isArray, clone;

    if(obj === target){
    return;
    }

    if(deep && obj instanceof Array){
    target = angular.unique(target.concat(obj));
    }
    else{
    for(var key in obj){
    src = target[key];
    copy = obj[key];
    @@ -38,7 +79,7 @@
    continue;
    }

    if(deep && copy && (angular.isPlainObject(copy) || (isArray = copy instanceof Array))){
    if((isArray = copy instanceof Array) || deep && copy && (angular.isPlainObject(copy))){
    if(isArray){
    clone = (src && src instanceof Array) ? src : [];
    }else{
    @@ -53,8 +94,8 @@
    target[key] = copy;
    }
    }
    });
    }
    });

    return target;
    };

    return target;
    };
  5. dysfunc revised this gist Oct 2, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion angular-deep-extend.js
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@
    src = target[key];
    copy = obj[key];

    if(target === copy){
    if(target === copy || src === copy){
    continue;
    }

  6. dysfunc revised this gist Sep 30, 2015. No changes.
  7. dysfunc revised this gist Sep 30, 2015. No changes.
  8. dysfunc revised this gist Sep 30, 2015. 1 changed file with 57 additions and 46 deletions.
    103 changes: 57 additions & 46 deletions angular-deep-extend.js
    Original file line number Diff line number Diff line change
    @@ -1,49 +1,60 @@
    /* Extends the destination object `dst` by copying all of the properties from the `src` object(s)
    * to `dst`. You can specify multiple `src` objects.
    * @param {Boolean} deep If true, the merge becomes recursive (optional aka deep copy)
    * @param {Object} dst Destination object.
    * @param {Object} src Source object(s).
    * @returns {Object} Reference to `dst`.
    *
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    */
    angular.extend = function(dst){
    var deep = false,
    i = 1;

    if(typeof(dst) === 'boolean'){
    deep = dst;
    dst = arguments[1] || {};
    i++;
    }

    angular.forEach([].slice.call(arguments, i), function(obj){
    var array, clone, copy, key, src;

    for(key in obj){
    src = dst[key];
    copy = obj[key];

    if(dst === copy){
    continue;
    }

    if((array = angular.isArray(copy)) || deep && copy && (angular.isObject(copy))){
    if(array){
    clone = (src && angular.isArray(src)) ? src : [];
    }else{
    clone = (src && angular.isObject(src)) ? src : {};
    /**
    * Determine whether an Object is a plain object or not (created using "{}" or "new Object")
    * @param {Object} obj Object we want to check
    * @return {Boolean} True/False result
    */
    angular.isPlainObject = function(obj){
    return !(typeof(obj) !== 'object' || obj && obj.nodeType || obj !== null && obj === obj.window || obj && obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf'));
    };

    /**
    * Merge the contents of two or more objects into the target object
    * @param {Boolean} deep If true, the merge becomes recursive (optional)
    * @param {Object} target The object receiving the new properties
    * @param {Object} arguments One or more additional objects to merge with the first
    * @return {Object} The target object with the new contents
    *
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    */
    angular.extend = function(target){
    var i = 1,
    deep = false;

    if(typeof(target) === 'boolean'){
    deep = target;
    target = arguments[1] || {};
    i++;
    }

    angular.forEach([].slice.call(arguments, i), function(obj){
    var src, copy, isArray, clone;

    for(var key in obj){
    src = target[key];
    copy = obj[key];

    if(target === copy){
    continue;
    }

    if(deep && copy && (angular.isPlainObject(copy) || (isArray = copy instanceof Array))){
    if(isArray){
    clone = (src && src instanceof Array) ? src : [];
    }else{
    clone = (src && angular.isPlainObject(src)) ? src : {};
    }

    isArray = false;

    target[key] = angular.extend(deep, clone, copy);
    }
    else if(copy !== undefined){
    target[key] = copy;
    }

    dst[key] = angular.extend(deep, clone, copy);
    }
    else if(copy !== undefined){
    dst[key] = copy;
    }
    }
    });

    return dst;
    }
    });

    return target;
    };

  9. dysfunc renamed this gist Sep 30, 2015. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions gistfile1.txt → angular-deep-extend.js
    Original file line number Diff line number Diff line change
    @@ -28,10 +28,8 @@
    if(dst === copy){
    continue;
    }

    if(deep && copy && (angular.isObject(copy) ||
    (array = angular.isArray(copy)))){


    if((array = angular.isArray(copy)) || deep && copy && (angular.isObject(copy))){
    if(array){
    clone = (src && angular.isArray(src)) ? src : [];
    }else{
  10. dysfunc revised this gist Mar 22, 2014. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,12 @@
    /* Extends the destination object `dst` by copying all of the properties from the `src` object(s)
    * to `dst`. You can specify multiple `src` objects.
    * @param {Boolean} deep If true, the merge becomes recursive (optional)
    * @param {Boolean} deep If true, the merge becomes recursive (optional aka deep copy)
    * @param {Object} dst Destination object.
    * @param {Object} src Source object(s).
    * @returns {Object} Reference to `dst`.
    *
    * angular.extend(object, object2) // shallow copy
    * angular.extend(true, object, object2) // deep copy
    */
    angular.extend = function(dst){
    var deep = false,
  11. dysfunc created this gist Mar 22, 2014.
    48 changes: 48 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    /* Extends the destination object `dst` by copying all of the properties from the `src` object(s)
    * to `dst`. You can specify multiple `src` objects.
    * @param {Boolean} deep If true, the merge becomes recursive (optional)
    * @param {Object} dst Destination object.
    * @param {Object} src Source object(s).
    * @returns {Object} Reference to `dst`.
    */
    angular.extend = function(dst){
    var deep = false,
    i = 1;

    if(typeof(dst) === 'boolean'){
    deep = dst;
    dst = arguments[1] || {};
    i++;
    }

    angular.forEach([].slice.call(arguments, i), function(obj){
    var array, clone, copy, key, src;

    for(key in obj){
    src = dst[key];
    copy = obj[key];

    if(dst === copy){
    continue;
    }

    if(deep && copy && (angular.isObject(copy) ||
    (array = angular.isArray(copy)))){

    if(array){
    clone = (src && angular.isArray(src)) ? src : [];
    }else{
    clone = (src && angular.isObject(src)) ? src : {};
    }

    dst[key] = angular.extend(deep, clone, copy);
    }
    else if(copy !== undefined){
    dst[key] = copy;
    }
    }
    });

    return dst;
    }