programing

Node.js에서 객체 복제

new-time 2020. 5. 15. 22:42
반응형

Node.js에서 객체 복제


node.js에서 객체를 복제하는 가장 좋은 방법은 무엇입니까예를 들어 다음과 같은 상황을 피하고 싶습니다.

var obj1 = {x: 5, y:5};
var obj2 = obj1;
obj2.x = 6;
console.log(obj1.x); // logs 6

객체에는 속성으로 복잡한 유형이 포함될 수 있으므로 간단한 for (var x in obj1)로는 해결되지 않습니다. 재귀 복제본을 직접 작성해야합니까 아니면 보이지 않는 것이 내장되어 있습니까?


가능성 1

프릴이 적은 사본 :

var obj2 = JSON.parse(JSON.stringify(obj1));

가능성 2 (더 이상 사용되지 않음)

주의 :

이제이 솔루션은

Node.js 문서

에서 더 이상 사용되지 않는 것으로 표시됩니다 .

util._extend () 메소드는 내부 Node.js 모듈 외부에서 사용되도록 설계되지 않았습니다. 커뮤니티는 어쨌든 그것을 찾아서 사용했습니다.더 이상 사용되지 않으며 새 코드에서 사용해서는 안됩니다. JavaScript는 Object.assign ()을 통해 매우 유사한 내장 기능을 제공합니다.

원래 답변 :

:얕은 사본의 경우 노드의 내장

util._extend()

기능을 사용하십시오.

var extend = require('util')._extend;

var obj1 = {x: 5, y:5};
var obj2 = extend({}, obj1);
obj2.x = 6;
console.log(obj1.x); // still logs 5

노드

_extend

기능 의 소스 코드 는 다음에 있습니다 :

https://github.com/joyent/node/blob/master/lib/util.js

exports._extend = function(origin, add) {
  // Don't do anything if add isn't an object
  if (!add || typeof add !== 'object') return origin;

  var keys = Object.keys(add);
  var i = keys.length;
  while (i--) {
    origin[keys[i]] = add[keys[i]];
  }
  return origin;
};

 

Object.assign

언급되지 않은 것이 놀랍습니다 .

let cloned = Object.assign({}, source);

사용 가능한 경우 (예 : Babel)

객체 스프레드 연산자를

사용할 수 있습니다 .

let cloned = { ... source };

Object.defineProperty(Object.prototype, "extend", {
    enumerable: false,
    value: function(from) {
        var props = Object.getOwnPropertyNames(from);
        var dest = this;
        props.forEach(function(name) {
            if (name in dest) {
                var destination = Object.getOwnPropertyDescriptor(from, name);
                Object.defineProperty(dest, name, destination);
            }
        });
        return this;
    }
});

사용할 수있는 확장 방법을 정의합니다. 이 기사에서 코드가 나온다

.


var obj2 = JSON.parse(JSON.stringify(obj1));

JQuery에서 확장 기능을 사용할 수 있습니다.

var newClone= jQuery.extend({}, oldObject);  
var deepClone = jQuery.extend(true, {}, oldObject); 

Node.js 플러그인도 있습니다 :

https://github.com/shimondoodkin/nodejs-clone-extend

JQuery 또는 플러그인없이 수행하려면 여기를 읽으십시오.

http://my.opera.com/GreyWyvern/blog/show.dml/1725165


 

underscore.js를

확인하십시오 . 그것은

복제

확장

과 다른 많은 유용한 기능을 가지고 있습니다.이것은 유용 할 수 있습니다 :

Node.js와 함께 밑줄 모듈 사용


"자신의 롤"을 원하지 않는 경우 일부 노드 모듈이 있습니다. 이것은 좋아 보인다 :

https://www.npmjs.com/package/clone

순환 참조를 포함하여 모든 종류의 물건을 처리하는 것처럼 보입니다. 로부터

github의의

페이지 :

복제 마스터는 개체, 배열, 날짜 개체 및 RegEx 개체를 복제합니다. 모든 것이 재귀 적으로 복제되므로 예를 들어 객체의 배열에서 날짜를 복제 할 수 있습니다. [...] 순환 참조? 네!

이 코드는 작동하는 원인이기도합니다.

Object.create ()

메서드는 지정된 프로토 타입 객체와 속성으로 새 객체를 만듭니다.

var obj1 = {x:5, y:5};

var obj2 = Object.create(obj1);

obj2.x; //5
obj2.x = 6;
obj2.x; //6

obj1.x; //5

NodeJS에서 객체를 복제하는 간단하고 빠른 방법은 Object.keys (obj) 메소드를 사용하는 것입니다

var a = {"a": "a11", "b": "avc"};
var b;

for(var keys = Object.keys(a), l = keys.length; l; --l)
{
   b[ keys[l-1] ] = a[ keys[l-1] ];
}
b.a = 0;

console.log("a: " + JSON.stringify(a)); // LOG: a: {"a":"a11","b":"avc"} 
console.log("b: " + JSON.stringify(b)); // LOG: b: {"a":0,"b":"avc"}

Object.keys 메소드에는 JavaScript 1.8.5가 필요합니다. nodeJS v0.4.11은이 방법을 지원합니다물론 중첩 객체의 경우 재귀 기능을 구현해야합니다.


다른 솔루션은 기본 JSON (JavaScript 1.7에서 구현 됨)을 사용하는 것이지만 이전보다 훨씬 느립니다 (~ 10 배 느림)

var a = {"a": i, "b": i*i};
var b = JSON.parse(JSON.stringify(a));
b.a = 0;

Github에는보다 직접적인 포트를 목표로하는 프로젝트도 있습니다

jQuery.extend()

.

https://github.com/dreamerslab/node.extend

 

jQuery 문서

에서 수정 된 예 :

var extend = require('node.extend');

var object1 = {
    apple: 0,
    banana: {
        weight: 52,
        price: 100
    },
    cherry: 97
};

var object2 = {
    banana: {
        price: 200
    },
    durian: 100
};

var merged = extend(object1, object2);

There is another library lodash, it has clone and cloneDeep, also many other useful function.


Looking for a true clone option, I stumbled across ridcully's link to here:

http://my.opera.com/GreyWyvern/blog/show.dml/1725165

I modified the solution on that page so that the function attached to the Object prototype is not enumerable. Here is my result:

Object.defineProperty(Object.prototype, 'clone', {
    enumerable: false,
    value: function() {
        var newObj = (this instanceof Array) ? [] : {};
        for (i in this) {
        if (i == 'clone') continue;
            if (this[i] && typeof this[i] == "object") {
                newObj[i] = this[i].clone();
            } else newObj[i] = this[i]
        } return newObj;
    }
});

Hopefully this helps someone else as well. Note that there are some caveats... particularly with properties named "clone". This works well for me. I don't take any credit for writing it. Again, I only changed how it was being defined.


You can also use SugarJS in NodeJS.

http://sugarjs.com/

They have a very clean clone feature: http://sugarjs.com/api/Object/clone


If you're using coffee-script, it's as easy as:

newObject = {}
newObject[key] = value  for own key,value of oldObject

Though this isn't a deep clone.


None of the answers satisfied me, several don't work or are just shallow clones, answers from @clint-harris and using JSON.parse/stringify are good but quite slow. I found a module that does deep cloning fast: https://github.com/AlexeyKupershtokh/node-v8-clone


There is no built-in way to do a real clone (deep copy) of an object in node.js. There are some tricky edge cases so you should definitely use a library for this. I wrote such a function for my simpleoo library. You can use the deepCopy function without using anything else from the library (which is quite small) if you don't need it. This function supports cloning multiple data types, including arrays, dates, and regular expressions, it supports recursive references, and it also works with objects whose constructor functions have required parameters.

Here is the code:

//If Object.create isn't already defined, we just do the simple shim, without the second argument,
//since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
    object_create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

/**
 * Deep copy an object (make copies of all its object properties, sub-properties, etc.)
 * An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
 * that doesn't break if the constructor has required parameters
 * 
 * It also borrows some code from http://stackoverflow.com/a/11621004/560114
 */ 
function deepCopy = function deepCopy(src, /* INTERNAL */ _visited) {
    if(src == null || typeof(src) !== 'object'){
        return src;
    }

    // Initialize the visited objects array if needed
    // This is used to detect cyclic references
    if (_visited == undefined){
        _visited = [];
    }
    // Ensure src has not already been visited
    else {
        var i, len = _visited.length;
        for (i = 0; i < len; i++) {
            // If src was already visited, don't try to copy it, just return the reference
            if (src === _visited[i]) {
                return src;
            }
        }
    }

    // Add this object to the visited array
    _visited.push(src);

    //Honor native/custom clone methods
    if(typeof src.clone == 'function'){
        return src.clone(true);
    }

    //Special cases:
    //Array
    if (Object.prototype.toString.call(src) == '[object Array]') {
        //[].slice(0) would soft clone
        ret = src.slice();
        var i = ret.length;
        while (i--){
            ret[i] = deepCopy(ret[i], _visited);
        }
        return ret;
    }
    //Date
    if (src instanceof Date) {
        return new Date(src.getTime());
    }
    //RegExp
    if (src instanceof RegExp) {
        return new RegExp(src);
    }
    //DOM Element
    if (src.nodeType && typeof src.cloneNode == 'function') {
        return src.cloneNode(true);
    }

    //If we've reached here, we have a regular object, array, or function

    //make sure the returned object has the same prototype as the original
    var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
    if (!proto) {
        proto = src.constructor.prototype; //this line would probably only be reached by very old browsers 
    }
    var ret = object_create(proto);

    for(var key in src){
        //Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
        //For an example of how this could be modified to do so, see the singleMixin() function
        ret[key] = deepCopy(src[key], _visited);
    }
    return ret;
};

npm install node-v8-clone

Fastest cloner, it open native clone method from node.js

var clone = require('node-v8-clone').clone;
var newObj = clone(obj, true); //true - deep recursive clone

Another solution is to encapsulate directly in the new variable using: obj1= {...obj2}


You can prototype object and then call object instance every time you want to use and change object:

function object () {
  this.x = 5;
  this.y = 5;
}
var obj1 = new object();
var obj2 = new object();
obj2.x = 6;
console.log(obj1.x); //logs 5

You can also pass arguments to object constructor

function object (x, y) {
   this.x = x;
   this.y = y;
}
var obj1 = new object(5, 5);
var obj2 = new object(6, 6);
console.log(obj1.x); //logs 5
console.log(obj2.x); //logs 6

Hope this is helpful.

참고URL : https://stackoverflow.com/questions/5055746/cloning-an-object-in-node-js

반응형