关于mongoose的一个问题[已解决]
发布于 10 年前 作者 yukjin 3803 次浏览 最后一次编辑是 8 年前 来自 问答
    Words.find({},function(err,words){
        if(err){
            callback(err);
        }else{
            for(var index in words){
                words[index].create_time=tools.formatDate(words[index].create_time,true);
                console.log(words[index].create_time);
                console.log(tools.formatDate(words[index].create_time,true))
            }
			callback(null,words);
        }
    });

上面打印结果是 Tue Dec 16 2014 15:08:00 GMT+0800 (CST) 25分钟前 Tue Dec 16 2014 15:08:53 GMT+0800 (CST) 24分钟前

我想问为什么理应被格式化了的words[index].create_time仍然是以前的样子

4 回复

words[index] 是一个被Mongoose管理的对象, 对于它的值的设置其实是执行了一个方法调用(用Object.defineProperty来定义的, 具体可见 mongoose/lib/document.js中定义的define方法)

    set: function (v) {
          if (v instanceof Document) v = v.toObject();
          return (this.$__.scope || this).set(path, v);
    }

在赋值时, Document.prototype.set = function (path, val, type, options) {} 会被执行, 其中与你问题相关的代码如下:

   var shouldSet = this.$__try(function(){           // 尝试看能否赋值
    val = schema.applySetters(val, self, false, priorVal);    // 基本上可以理解为将val转型为schema定义的字段类型后赋值
  });
  if (shouldSet) {
    this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
  }

出现你描述的问题, 应该是words[index].create_time定义的类型 和 tools.formatDate(words[index].create_time,true)的类型不同而没有设置成功.

@GuoZhang 请问为什么一个普通的赋值操作会导致一个方法的调用?能否告知一下原理活着说一下用到了什么知识点我自己去查一下,另外我看nodeclub源码里好像是通过赋值格式化时间的,是我遗漏了什么?

关于Object.defineProperty方法可以参考这里: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

我可以给你一个简单的例子:

function User(firstname, lastname) {  // 构造函数
  this.firstname = firstname;
  this.lastname = lastname;
}

// 为User.prototype定义一个名为'fullname'的属性
Object.defineProperty(User.prototype, 'fullname', {
  enumerable: true,
  configurable: true,
  get: function (){   // 访问时执行
    return this.firstname + '*' + this.lastname;
  },
  set: function (fullname) { // 设置时执行
    var tokens = fullname.split('*');
    this.firstname = tokens[0];
    this.lastname  = tokens[1];
  }
});

// 使用示例
var user = new User('Zhang', 'Guo');
console.log(user.fullname);  // output: Zhang*Guo
user.fullname = 'Brian*Zhang';
console.log(user.firstname, user.lastname); // output: Brian Zhang

再回到你的问题,words[index] 是一个Mongoose管理的对象。它不是一个普通的对象,它的属性具有上述示例代码那样的特性。如果你要把它做成一个普通的对象(属性都是简单的值访问/修改),可以在查询数据库是使用lean()方法(http://mongoosejs.com/docs/api.html#query_Query-lean)或使用对象的toObject()方法(http://mongoosejs.com/docs/api.html#document_Document-toObject)。

@GuoZhang 谢谢了,终于解决了

回到顶部