gpt4 book ai didi

javascript - 在原型(prototype)方法中从内部函数修改实例变量

转载 作者:行者123 更新时间:2023-11-29 22:24:54 24 4
gpt4 key购买 nike

我正在尝试将数据库中的数据建模为服务器端 JavaScript (Node) 中的“类”。目前,我只是在适当的地方使用带有原型(prototype)方法的传统构造函数模式,并将构造函数公开为整个 module.exports。这是服务器端这一事实对于问题的核心并不重要,但我想我会提供它作为引用。

代码的问题区域如下所示:

User.prototype.populate = function() {  
var that = this;
db.collection("Users").findOne({email : that.email}, function(err, doc){
if(!err) {
that.firstName = doc.firstName;
that.lastName = doc.lastName;
that.password = doc.password;
}
console.log(that); //expected result
});
console.log(that); //maintains initial values
};

每当我调用此函数时,一旦 findOne() 完成,对对象的更改就不会保留。我意识到 this 的范围更改为具有新函数范围的全局对象,因此我将其引用保持为 that。如果 console.log(that) 来自匿名函数,数据会按预期显示在它的属性中。但是,如果我在函数完成后记录 that,它会保持函数开始时的状态。

这是怎么回事,我怎样才能按预期更改实例变量?

最佳答案

"However, if I log that once the function has finished, ..."

由此我假设你正在做这样的事情......

var user = new User

user.populate();

console.log(user);

如果是这样,console.log 将在调用 .findOne()异步回调之前运行很长时间。

任何依赖于对 findOne 的响应的代码都需要在回调中调用。


编辑:您的更新与我上面的示例略有不同,但原因是一样的。

将回调传递给 findOne 方法的全部原因是它执行异步 事件。如果没有,则没有回调的理由。您只需将内部代码直接放在对 findOne 的调用之后,就像您对 console.log() 所做的那样。

但是因为是异步,后面的代码不会等待执行。这就是您在控制台中获得未填充对象的原因。

如果您为每个 console.log() 添加标签,您将看到它们执行的顺序不正确。


var that = this;    
db.collection("Users").findOne({email : that.email}, function(err, doc){
if(!err) {
that.firstName = doc.firstName;
that.lastName = doc.lastName;
that.password = doc.password;
}
console.log("inside the callback", that); // this happens Last!!!
});

console.log("outside the callback", that); // this happens First!!!

因此,一旦您观察到 console.log 调用的顺序,就会清楚空调用发生在回调中的调用之前。


编辑:您还可以让您的 .populate() 方法接收在 .findOne< 中调用的回调 回调。

User.prototype.createNickName = function () {
this.nickname = this.firstName.slice(0,3) + '_' + this.lastName.slice(0,3);
};

// >>>------------------------------v----receive a function argument...
User.prototype.populate = function(callback_func) {
var that = this;
db.collection("Users").findOne({email : that.email}, function(err, doc){
if(!err) {
that.firstName = doc.firstName;
that.lastName = doc.lastName;
that.password = doc.password;
}

// all users will have the "createNickName()" method invoked
that.createNickName();

// ...and invoke it in the callback.
callback_func.call(that);

// By using .call(), I'm setting the "this" value
// of callback_func to whatever is passed as the first argument
});
};

   // this user wants to log the firstName property in all caps
var user1 = new User;

user1.populate(function() {
console.log(this.firstName.toUpperCase());
});


// this user wants to log the the whole name
var user2 = new User;

user2.populate(function() {
console.log(this.firstName + ' ' + this.lastName);
});


// this user wants to verify that the password is sufficiently secure
var user3 = new User;

user3.populate(function() {
console.log(verify_password(this.password));
});

关于javascript - 在原型(prototype)方法中从内部函数修改实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10150207/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com