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仍然是以前的样子
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)。