从javascript对象中剥离方法

Strip methods off javascript object

本文关键字:剥离 方法 对象 javascript      更新时间:2023-09-26

在一次回购中,我看到了一行。

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

我认为这是在试图从对象中剥离任何方法。我真的看不出它在做什么。有没有更有效的方法来尝试?节点是否对此进行了优化?

在您现在公开的代码上下文中,此技术用于复制传递给函数的对象,这样对该对象的修改就不会修改原始对象。以下是您链接的上下文:

// 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实际上并不是定义一个新的变量。由于msg已经在此范围中定义为函数参数,因此var msg不会重新声明它(从技术上讲,这是使用var的代码中的一个错误)。


使用这种类型的代码的通常原因是克隆对象(对对象进行深度复制,复制包括嵌入对象和数组在内的所有属性)。

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"

注意:这只适用于纯Object类型的对象的完整副本,并且不具有作为函数的自定义属性。而且,因为JSON.stringify()不支持循环引用或自引用,所以您不能拥有其中任何一个。而且,如果对同一对象有多个引用,则每个引用都将复制到一个新的单独对象。而且,JSON.stringify()JSON.parse()的组合不支持普通Object以外的对象,如RegExpDate或您自己的任何自定义对象(它们将它们变成普通对象)。因此,这个程序有一些局限性,但它对大多数情况下都很简单。


根据Matt(在评论中),可以在这里看到一个自定义函数,用于创建一个支持循环引用并支持某些类型自定义对象的对象的克隆。


如果读到这篇文章的人没有意识到,将一个对象分配给另一个变量不会在Javascript中复制。Javascript中的赋值类似于设置对同一对象的指针引用。然后,每个变量都指向相同的底层对象,因此在两种情况下,通过任一变量修改对象最终都会修改相同的对象,如下所示:

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"

因此,偶尔需要对对象进行实际的深度复制。

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

如果您想要剥离作为函数的属性,则循环遍历对象并检查该属性是否为函数:

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

或者,也许你希望实现的是两者的结合。