Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在原型方法中从内部函数修改实例变量_Javascript_Oop_Scope - Fatal编程技术网

Javascript 在原型方法中从内部函数修改实例变量

Javascript 在原型方法中从内部函数修改实例变量,javascript,oop,scope,Javascript,Oop,Scope,我试图在服务器端JavaScript(节点)中将数据库中的数据建模为“类”。 目前,我只是在适当的地方使用传统的构造函数模式和原型方法,并将构造函数函数公开为整个模块.exports。事实上,这是服务器端对于问题的核心并不重要,但我想我会提供它作为参考 代码的问题区域如下所示: User.prototype.populate = function() { var that = this; db.collection("Users").findOne({email :

我试图在服务器端JavaScript(节点)中将数据库中的数据建模为“类”。 目前,我只是在适当的地方使用传统的构造函数模式和原型方法,并将构造函数函数公开为整个
模块.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
的作用域更改为具有新函数作用域的全局对象,因此我将其引用保持为
this
。如果从匿名函数中选择
console.log(that)
,则数据将按预期显示在其属性中。但是,如果我在函数完成后记录该,它将保持函数开始时的状态

这里发生了什么,我如何按照预期更改实例变量

“但是,如果我在函数完成后记录,…”

我猜你是在做这样的事

var user = new User

user.populate();

console.log(user);
如果是这样的话,
console.log
将在调用对
.findOne()
的异步回调之前很久运行

任何依赖于
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
    });
};

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

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

但由于它是异步的,后续代码不会等待执行。这就是为什么要在控制台中获取未填充的对象

如果将标签添加到每个
console.log()


因此,观察
console.log
调用的顺序就可以清楚地看到,空的调用发生在回调中的调用之前

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
    });
};

EDIT:您还可以让
.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
    });
};


没错。尽管这种情况在外部调用日志记录user.populate()中以及在populate()方法本身中都会发生(但不在findOne()的范围内)。我已经更新了帖子以反映我的意思。@user574930:刷新浏览器。我已经更新了我的答案。那么,有了这些知识,我如何才能实现我正在寻找的效果,在哪里我可以简单地调用populate()方法并知道对象的属性将得到更新?通过传递更多回调-如果你想在属性更新时呈现页面,将其放入一个函数中,并将其传递到链中,然后在db.collection回调中调用它。@DuxPrime:好吧,您需要将您的代码流视为转移到传递给
findOne
的回调中。因此,在这里,您将继续您的编码。此外,重要的是要记住,函数(因此函数)可以像任何其他数据一样传递。