剥离JavaScript对象的方法

在一个回购中,我看到一条线。

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

我认为这是试图剥离任何方法的对象。 我真的不能看到它做任何事情。 有没有更有效的方法来尝试这个? 节点是否优化了这个?

在你现在已经公开的代码上下文中 ,这个技术被用来创build一个传递给一个函数的对象的副本,以便对该对象的修改不会修改原始的。 以下是您的链接的上下文:

 // 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 } 

注意:此剪辑中包含msg.body.unshift(null) 。 如果没有这个副本,那将会修改原来的对象。

另外请注意,重新声明var msg实际上并没有定义一个新的variables。 由于msg已经在此作用域中定义为函数参数,因此它不会被var msg重新声明(这在技术上是代码中使用var的错误)。


使用这种types的代码的通常原因是克隆一个对象(复制包含embedded对象和数组的所有属性的对象的深层副本)。

 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" 

注意:这只能作为一个普通的对象types的对象的完整副本,并没有自定义的属性是函数。 而且,由于JSON.stringify()不支持循环引用或自引用,因此不能使用这些引用。 而且,如果您有多个对同一对象的引用,则每个引用将被复制到一个新的独立对象。 而且, JSON.stringify()JSON.parse()的组合不支持除普通Object例如RegExpDate或任何自定义对象(它们将它们转换为普通对象)以外的对象)。 所以,这个程序有一些限制,但是对于大多数情况来说,这个限制很简单。


每马特(在注释),一个自定义函数创build一个支持循环引用的对象的克隆,并支持某些types的自定义对象可以在这里看到。


如果读者没有意识到,将对象赋值给另一个variables不会在Javascript中进行复制。 在Javascript中的赋值就像设置一个指向同一对象的指针一样。 然后每个variables都指向相同的底层对象,所以通过这两个variables修改对象最终会修改同一个对象,如下所示:

 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" 

因此,偶尔需要做一个对象的实际深层拷贝。

如果从原型中删除方法是您想要的,请考虑创build一个新对象并转移所有旧对象的属性。

如果剥离属性是一个函数是你想要的,遍历对象并检查属性是否是一个函数:

 for(key in ob) { if(typeof ob[key] === 'function') { delete ob[key]; } } 

或者,你希望完成的是两者的结合。