Javascript / NodeJS:传入对象似乎覆盖了"self"-关闭问题

Javascript / NodeJS : Passed in object seems to overwrite "self" - closure issue?

本文关键字:quot self 问题 覆盖 NodeJS 对象 Javascript      更新时间:2023-09-26

我的第一个Stackoverflow问题(我记得)。在缺席多年并尝试了Node和Javascript之后,我正在慢慢地回到开发中。

我希望这真的很简单,但我就是看不出我做错了什么。

我有一个相当简单的javascript对象的两个实例。当我将该对象的一个实例传递给函数时,其他的东西就失效了。

  • 我第一次引用"self"值,它很好

  • 然后在传入的对象上调用一个函数。

  • 如果我尝试之后再次引用"self",似乎"self"已被传入的对象覆盖。

对象来源:

"use strict";
//simple object
module.exports.SimpleObject = function SimpleObject(inputName) {
    try{
        var self = this; //closure so we don't lose this reference in callbacks
        self.name = inputName; 
    }
    catch(err) {
        console.log('Unable to create SimpleObject: '+err);
    }
    SimpleObject.prototype.getName = function() {
        self = this;
        return self.name;
    }
    SimpleObject.prototype.nestedOverwrite = function(anObject) {
        self = this;
        return "#1 self.name: "+self.name+" ObjectName: "+anObject.getName()+" #2 self.name: "+self.name;
    }
    return this;
}

下面是测试用例:

var  testSimpleObjectModule = require('./simpleObject');
var o0 = new testSimpleObjectModule.SimpleObject('test0');
var o1 = new testSimpleObjectModule.SimpleObject('test1');
console.log(o0.nestedOverwrite(o1));
console.log(o1.nestedOverwrite(o0));

下面是我得到的输出:

#1 self.name: test0 ObjectName: test1 #2 self.name: test1
#1 self.name: test1 ObjectName: test0 #2 self.name: test0

希望你能看到,在每种情况下,第一个调用self.name是好的,第二个失去了上下文。

任何帮助非常感谢!

每次构造函数被调用时,您都将函数分配给分配给新SimpleObject 的原型对象。因此,第二次调用构造函数时,原型被更新,并且之前使用原型创建的任何对象都开始使用new函数(具有新的self值)。

如果你想让这些闭包有self,不要把它们放在原型上,把它们放在this上(后面有更多)。

但是请注意,在您引用的代码中,没有理由使用self变量。您可以使用原型函数(这更有效),而不是为每个实例创建函数。为此,使用this(不将其赋值给self)并在构造函数之外定义函数,如下所示:

"use strict";
//simple object
module.exports.SimpleObject = function SimpleObject(inputName) {
    this.name = inputName;
};
SimpleObject.prototype.getName = function() {
    return this.name;
};
SimpleObject.prototype.nestedOverwrite = function(anObject) {
    return "#1 this.name: "+this.name+" ObjectName: "+anObject.getName()+" #2 this.name: "+this.name;
};

但是如果你对self做了一些你没有显示的事情,这意味着你真的需要它(例如,当函数被调用时,你不能信任this的值 &mdasdh;它们被用作回调/事件处理程序等),您可以这样做:

"use strict";
//simple object
module.exports.SimpleObject = function SimpleObject(inputName) {
    var self = this;
    self.name = inputName; 
    self.getName = function() {
        return self.name;
    };
    self.nestedOverwrite = function(anObject) {
        return "#1 self.name: "+self.name+" ObjectName: "+anObject.getName()+" #2 self.name: "+self.name;
    };
};

指出:

  • 没有理由在构造函数的末尾加上return this

  • 注意,我们不想在每个函数中都做self = this;;使用self的全部意义在于,当调用函数时,您不希望依赖于this具有正确的值。(如果你可以依靠this被设置,那么使用函数的原型版本)

  • 永远不要在构造函数中捕获异常,然后说你不能进行构造,因为这样做,你允许new Xyz表达式完成,并且未初始化的对象作为表达式的结果返回。出于这个原因,我已经从上面删除了try/catch

  • 我推荐而不是依赖于自动分号插入的恐惧。以分号结束表达式(包括将函数赋值给变量或属性时)