Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strip methods off javascript object

In one repo I saw a line.

var foo = JSON.parse(JSON.stringify(foo));

I think this is trying to strip any methods off the object. I can't really see it doing anything else. Is there a more efficient way to attempt this? Does node optimize this?

like image 809
MKaras Avatar asked Mar 20 '15 01:03

MKaras


People also ask

How do I remove a property from an object?

Remove Property from an ObjectThe delete operator deletes both the value of the property and the property itself. After deletion, the property cannot be used before it is added back again. The delete operator is designed to be used on object properties. It has no effect on variables or functions.

How do I remove a property from an object without mutating?

A better way to delete a property without mutating is by using spread operator. const {worth, … newPerson} = person; console.

How do you destroy an object in JavaScript?

The destroy() method of the client object explicitly destroys that instance of the object and all its associated properties. If this method is not called, the JavaScript runtime will destroy the object after 10 minutes or after the time specified with the client. expiration() method.

How do you remove one property from an object in TypeScript?

To remove a property from an object in TypeScript, mark the property as optional on the type and use the delete operator. You can only remove properties that have been marked optional from an object.


1 Answers

In the code context you have now disclosed, this technique is being used to make a copy of an object passed to a function so that modifications to that object will not modify the original. Here's the context from your link:

// route reply/error
this.connection.on('message', function(msg) {
   var msg = JSON.parse(JSON.stringify(msg));
   var handler;
   if (msg.type == constants.messageType.methodReturn || msg.type == constants.messageType.error) {
       handler = self.cookies[msg.replySerial];
       if (msg.type == constants.messageType.methodReturn && msg.body)
          msg.body.unshift(null); // first argument - no errors, null
       if (handler) {
          delete self.cookies[msg.replySerial];
          var props = {
             connection: self.connection,
             bus: self,
             message: msg,
             signature: msg.signature
          };
          if (msg.type == constants.messageType.methodReturn)
             handler.apply(props, msg.body); // body as array of arguments
          else
             handler.call(props, msg.body);  // body as first argument
       }

Note: the line in this clip that contains msg.body.unshift(null). That would be modifying the original object if this copy was not made.

Also, note that redeclaring var msg is not actually defining a new variable. Since msg is already defined in this scope as the function argument, it is not redeclared by the var msg (this is technically a mistake in the code to use the var).


The usual reason for using this type of code is to clone an object (make a deep copy of the object where all properties including embedded objects and arrays are copied).

var obj = {
   list: [1,2,3],
   items: [{language: "English", greeting: "hello"}, 
           {language: "Spanish", greeting: "hola"}, 
           {language: "French", greeting: "bonjour"}]
}

// make a completely independent copy of obj
var copy = JSON.parse(JSON.stringify(obj));

copy.items[0].greeting = "Yo";

console.log(obj.items[0].greeting);    // "hello"
console.log(copy.items[0].greeting);   // "Yo"

Note: this only works as a full copy with objects that are a plain Object type and do not have custom properties that are functions. And, because JSON.stringify() does not support circular references or self references, you can't have any of those. And, if you have multiple references to the same object, each reference will be copied to a new separate object. And, the combination of JSON.stringify() and JSON.parse() don't support objects other than a plain Object such as RegExp, Date or any of your own custom objects (they turn them into plain Objects). So, there are some limitations of this procedure, but it works quite simply for the majority of cases.


Per Matt (in comments), a custom function to create a clone of an object that does support circular references and does support some types of custom objects can be seen here.


In case anyone reading this doesn't realize, assigning an object to another variable does not make a copy in Javascript. The assignment in Javascript is like setting a pointer reference to the same object. Each variable then points to the same underlying object so modifying the object through either variable ends up modifying the same object in both cases like this:

var obj = {
   list: [1,2,3],
   items: [{language: "English", greeting: "hello"}, 
           {language: "Spanish", greeting: "hola"}, 
           {language: "French", greeting: "bonjour"}]
}

var copy = obj;

// modify copy 
copy.items[0].greeting = "Yo";

// both obj and copy refer to the exact same object
console.log(obj.items[0].greeting);    // "Yo"
console.log(copy.items[0].greeting);   // "Yo"

Thus, the occasional need to make an actual deep copy of an object.

like image 180
jfriend00 Avatar answered Sep 22 '22 19:09

jfriend00